예제 #1
0
    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()
예제 #2
0
파일: util.py 프로젝트: chaoticjoy/FMPy
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)
예제 #3
0
파일: util.py 프로젝트: vruge/FMPy
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)
예제 #4
0
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)
예제 #5
0
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)
예제 #6
0
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
예제 #7
0
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
예제 #8
0
    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()
예제 #9
0
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
예제 #10
0
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()
예제 #11
0
    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
예제 #12
0
파일: util.py 프로젝트: m-kessler/FMPy
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)
예제 #13
0
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
예제 #14
0
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)
예제 #16
0
파일: util.py 프로젝트: vruge/FMPy
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)
예제 #17
0
파일: env_fmu.py 프로젝트: bsl546/energym
    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
예제 #18
0
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)
예제 #19
0
    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()
예제 #20
0
 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
예제 #21
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)
예제 #22
0
    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)
예제 #23
0
파일: util.py 프로젝트: vruge/FMPy
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)
예제 #24
0
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)
예제 #25
0
    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()
예제 #26
0
    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
예제 #27
0
    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)
예제 #28
0
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()
예제 #29
0
    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)
예제 #30
0
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