def test_validate_derivatives(self): message = None try: read_model_description('CoupledClutches.fmu', validate=True, validate_variable_names=False) except Exception as e: message = str(e) self.assertEqual(message, 'The unit "" of variable "inputs" (line 183) is not defined.')
def test_validate_variable_name(self): message = None try: read_model_description('CoupledClutches.fmu', validate=False, validate_variable_names=True) except Exception as e: message = str(e) self.assertTrue(message.startswith('"CoupledClutches_r(19)" (line 192) is not a legal variable name for naming convention "structured".'))
def test_validate_variable_names(self): problems = [] try: read_model_description('CoupledClutches.fmu', validate=True, validate_variable_names=True) except ValidationError as e: problems = e.problems self.assertEqual(len(problems), 124)
def test_validate_derivatives(self): problems = [] try: read_model_description('CoupledClutches.fmu', validate=True, validate_variable_names=False) except ValidationError as e: problems = e.problems self.assertEqual( problems[0], 'The unit "" of variable "inputs" (line 183) is not defined.')
def test_validate_derivatives(self): message = None try: read_model_description('CoupledClutches.fmu', validate=True, validate_variable_names=False) except Exception as e: message = str(e) self.assertEquals( 'Failed to validate model description. 1 problems were found:\n\n- The unit "" of variable "inputs" (line 183) is not defined.', message)
def test_validate_variable_names(self): message = "" try: read_model_description('CoupledClutches.fmu', validate=True, validate_variable_names=True) except Exception as e: message = str(e) self.assertTrue( message.startswith( 'Failed to validate model description. 124 problems were found:' ))
def validate_fmu(filename): """ Validate an FMU Returns: a list of the problems found """ from . import read_model_description try: read_model_description(filename, validate=True) except Exception as e: return [str(e)] return []
def add_cswrapper2(filename, outfilename=None): from fmpy.fmucontainer import Variable, Configuration, Component, create_fmu_container model_description = read_model_description(filename) model_identifier = model_description.modelExchange.modelIdentifier variables = [] for variable in model_description.modelVariables: variables.append( Variable(type=variable.type, variability=variable.variability, causality=variable.causality, initial=variable.initial, name=variable.name, start=variable.start, description=variable.description, mapping=[(model_identifier, variable.name)])) configuration = Configuration(variables=variables, components=[ Component(filename=filename, interfaceType='ModelExchange', name=model_identifier) ]) create_fmu_container(configuration, outfilename)
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 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 __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 test_type_definitions(self): """ Read the Type Definitions from the modelDescription.xml """ for fmi_version in ['1.0', '2.0']: filename = download_file( 'https://github.com/modelica/fmi-cross-check/raw/master/fmus/' + fmi_version + '/cs/win64/Dymola/2017/DFFREG/DFFREG.fmu') model_description = read_model_description(filename) real = model_description.typeDefinitions[0] self.assertEqual('Real', real.type) self.assertEqual('Modelica.SIunits.Time', real.name) self.assertEqual('Time', real.quantity) self.assertEqual('s', real.unit) logic = model_description.typeDefinitions[1] self.assertEqual('Enumeration', logic.type) self.assertEqual('Modelica.Electrical.Digital.Interfaces.Logic', logic.name) self.assertEqual(9, len(logic.items)) high_impedance = logic.items[4] self.assertEqual("'Z'", high_impedance.name) self.assertEqual(5, int(high_impedance.value)) self.assertEqual("Z High Impedance", high_impedance.description)
def __init__(self, fmu="testrig.fmu"): """ Prepares the FMU for start and retrieves the available the inputs, outputs and output matrices from it :param fmu: the name of the fmu that will be used """ file = os.path.realpath(os.path.join('../../fmus', fmu)) # TODO: validate file path self.model_description = fmpy.read_model_description(file) self.dt = 0 self.t = 0 self.inputs = [] self.time_step_input_ref = -1 for variable in self.model_description.modelVariables: if variable.causality == 'input': if not variable.name == "Input_time_step": self.inputs.append(variable) else: self.time_step_input_ref = variable.valueReference self.matrix_outputs = defaultdict(list) self.outputs = [] for variable in self.model_description.modelVariables: if variable.causality == 'output': self.outputs.append(variable) if cell_regex.match(variable.name): self.matrix_outputs[variable.name[:-4]].append( len(self.outputs) - 1) self.file = file self.fmu = None
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 test_type_definitions(self): """ Read the Type Definitions from the modelDescription.xml """ for fmi_version in ['1.0', '2.0']: download_file( 'https://trac.fmi-standard.org/export/HEAD/branches/public/Test_FMUs/FMI_' + fmi_version + '/CoSimulation/win64/Dymola/2017/DFFREG/DFFREG.fmu') model_description = read_model_description('DFFREG.fmu') real = model_description.typeDefinitions[0] self.assertEqual('Real', real.type) self.assertEqual('Modelica.SIunits.Time', real.name) self.assertEqual('Time', real.quantity) self.assertEqual('s', real.unit) logic = model_description.typeDefinitions[1] self.assertEqual('Enumeration', logic.type) self.assertEqual('Modelica.Electrical.Digital.Interfaces.Logic', logic.name) self.assertEqual(9, len(logic.items)) high_impedance = logic.items[4] self.assertEqual("'Z'", high_impedance.name) self.assertEqual(5, int(high_impedance.value)) self.assertEqual("Z High Impedance", high_impedance.description)
def validate(self, build_dir, fmi_types=['ModelExchange', 'CoSimulation'], models=models, compile=False): from fmpy.util import read_csv, validate_result for model in models: print(model) fmu_filename = os.path.join(build_dir, 'dist', model + '.fmu') if model == 'Feedthrough': start_values = { 'real_fixed_param': 1, 'string_param': "FMI is awesome!" } in_csv = os.path.join(test_fmus_dir, model, model + '_in.csv') input = read_csv(in_csv) else: start_values = {} input = None ref_csv = os.path.join(test_fmus_dir, model, model + '_ref.csv') for fmi_type in fmi_types: ref = read_csv(ref_csv) if compile: compile_platform_binary(fmu_filename) read_model_description(fmu_filename, validate_variable_names=True, validate_model_structure=True) result = simulate_fmu(fmu_filename, fmi_type=fmi_type, start_values=start_values, input=input, solver='Euler') dev = validate_result(result, ref) self.assertLess(dev, 0.2, "Failed to validate " + model)
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 __init__(self, name, options): super().__init__(name, options) if (options['tool'] == "IPSL") or (options['tool'] == "FMU"): if 'inputs' not in options: raise Exception("DynamicSimulation.init(): Inputs must be provided.") if 'outputs' not in options: raise Exception("DynamicSimulation.init(): Outputs must be provided.") if 'fmu' in options: myFMUid = options['fmu'] else: myFMUid = options['model_path'] + '\\' + options['model'] + '.fmu' modelDescription = read_model_description(myFMUid, validate=True) if options['tool'] == "IPSL": tIPSL = IPSLtranslator(modelDescription.modelVariables) else: tIPSL = FMPYtranslator(modelDescription.modelVariables) import copy DSnoInitopt = copy.deepcopy(options) self.inElemList = [] for i in options['inputs']: tranIn = tIPSL.translate(i) if len(tranIn)>1: ind = DSnoInitopt['inputs'].index(i) DSnoInitopt['inputs'].pop(ind) for j in reversed(tranIn): DSnoInitopt['inputs'].insert(ind,j) #pom = Demux(name + '->' + i, len(tranIn)) if i.find("Pg")>=0 or i.find("Qg")>=0: pom = Demux(name + '->' + i, len(tranIn)) elif i.find("Pd")>=0 or i.find("Qd")>=0: ind = tIPSL.getIndex(tranIn) pom = Demux(name + '->' + i, len(tranIn), VALUETYPES.REAL, {'ind' : ind}) self.add_element(pom) self.inElemList.append(pom) else: pom = Reflector(name + '->' + i) self.add_element(pom) self.inElemList.append(pom) if tIPSL.isSignal(i): self.setInputCondition("edge{" + i + "}", 'init') actualOutputs = DSnoInitopt['inputs'].copy() self.myTool = DynamicSimulationNoInit(name + '->DSnoInit', DSnoInitopt) self.add_element(self.myTool) cnt = 0 for i in range(0,len(self.inElemList)): for j in range(0,len(self.inElemList[i].output)): self.inElemList[i].connect(self.myTool,j+1,actualOutputs[cnt]) cnt += 1
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 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)
async def fmu_detail(request: web.Request): """ Get detailed information for the FMU with the given id Append /models to get the 3d models if any """ file = await find_in_dir(request.match_info['id'], request.app['settings'].FMU_DIR) model_description = read_model_description(file) return web.json_response(model_description, dumps=dumps)
def test_validate_variable_names(self): filename = download_file( url= 'https://github.com/modelica/fmi-cross-check/raw/master/fmus/2.0/me/win64/MapleSim/2015.1/CoupledClutches/CoupledClutches.fmu', checksum= 'af8f8ca4d7073b2d6207d8eea4a3257e3a23a69089f03181236ee3ecf13ff77f') problems = [] try: read_model_description(filename, validate=True, validate_variable_names=True) except ValidationError as e: problems = e.problems self.assertEqual(len(problems), 124)
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 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 test_read_model_description(self): unzipdir = os.path.join(os.environ['FMI3_FMUS_DIR'], 'linearOperatorcs30') model_description = read_model_description(unzipdir) fmu = FMU3Slave( guid=model_description.guid, unzipDirectory=unzipdir, modelIdentifier=model_description.coSimulation.modelIdentifier) fmu.instantiate() fmu.setupExperiment() fmu.enterInitializationMode() fmu.exitInitializationMode() variables = dict((v.name, v) for v in model_description.modelVariables) def get_real(variable): vr = (fmi3ValueReference * 1)(variable.valueReference) value = np.zeros(variable.extent) status = fmu.fmi3GetReal( fmu.component, vr, len(vr), cast(value.ctypes.data, POINTER(fmi3Float64)), value.size) self.assertEqual(status, fmi3OK) return value def set_real(variable, data): vr = (fmi3ValueReference * 1)(variable.valueReference) status = fmu.fmi3SetReal( fmu.component, vr, len(vr), cast(data.ctypes.data, POINTER(fmi3Float64)), data.size) self.assertEqual(status, fmi3OK) # get "in" in_data = get_real(variables['in']) self.assertTrue(np.all(in_data == [1, 1, 1])) # get "operator" operator_data = get_real(variables['operator']) self.assertTrue( np.all(operator_data.flat == [1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1])) # set "in" in_data[:] = [1, 2, 3] set_real(variables['in'], in_data) # get "out" out_data = get_real(variables['out']) self.assertTrue(np.all(out_data == [1, 2, 3, 6])) # clean up fmu.terminate() fmu.freeInstance()
def df_to_repr_jsonld(df, fmu, time_is_relative): """Render JSON-LD-representation of DataFrame.""" logger.debug("df:\n{}".format(df)) unit_map = { "W": UNIT.W, "kW.h": UNIT["KiloW-HR"], "deg": UNIT.DEG, } # Read model description desc = fmpy.read_model_description(fmu) # Iterate over columns of dataframe graph = graph_bind_prefixes(rdflib.Graph()) for label, series in df.items(): # Set unit to '1' if it is undefined # https://github.com/CATIA-Systems/FMPy/blob/master/fmpy/model_description.py#L154 model_variable = py_.find(desc.modelVariables, lambda x: x.name == label) if model_variable.unit is not None: unit = model_variable.unit else: unit = "1" logger.debug(f"{model_variable.name} / {unit}") # Define `sosa:ObservableProperty` for each column observable_iri = f"#{label}" observable_uriref = rdflib.URIRef(observable_iri) graph.add((observable_uriref, RDF.type, SOSA.ObservableProperty)) for index, value in series.items(): # Define `sosa:Observation` for each row observation_id = f"#{nanoid.generate(size=8)}" observation_uriref = rdflib.URIRef(observation_id) graph.add((observation_uriref, RDF.type, SOSA.Observation)) graph.add((observation_uriref, SOSA.observedProperty, observable_uriref)) # Define `qudt:QuantityValue` for each value result_uriref = rdflib.URIRef(f"{observation_id}_result") graph.add((result_uriref, RDF.type, QUDT.QuantityValue)) graph.add((result_uriref, QUDT.numericValue, rdflib.Literal(float(value)))) graph.add((result_uriref, QUDT.unit, unit_map[unit])) graph.add((observation_uriref, SOSA.hasResult, result_uriref)) # Define `time:Instant` for each index time_uriref = rdflib.URIRef(f"{observation_id}_time") time_literal = rdflib.Literal(index, datatype=XSD.dateTimeStamp) graph.add((time_uriref, RDF.type, TIME.Instant)) graph.add((time_uriref, TIME.inXSDDateTimeStamp, time_literal)) graph.add((observation_uriref, SOSA.phenomenonTime, time_uriref)) return json.loads(graph.serialize(format="application/ld+json"))
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 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 test_cswrapper(self): filename = 'CoupledClutches.fmu' download_test_file('2.0', 'ModelExchange', 'MapleSim', '2016.2', 'CoupledClutches', filename) model_description = read_model_description(filename) self.assertIsNone(model_description.coSimulation) add_cswrapper(filename) simulate_fmu(filename, fmi_type='CoSimulation')