Esempio n. 1
0
# output = []

# Start and stop time
start_time = 360  # THIS TRIGGERS THE WARNINGS
stop_time = inp_df["time"].iloc[-1]
output_interval = inp_df["time"].iloc[1] - inp_df["time"].iloc[0]

# Reset the FMU instance instead of creating a new one
fmu.reset()

# Simulate
result = simulate_fmu(
    filename=fmu_path,
    start_values=start_values,
    start_time=start_time,
    stop_time=stop_time,
    input=inp_struct,
    output=None,
    output_interval=output_interval,
    fmu_instance=fmu,
)

# Free the FMU instance and free the shared library
fmu.freeInstance()

# Result to DataFrame
result = struct_arr_to_df(result)
print(result)
plt.plot(result)
plt.show()
Esempio n. 2
0
            if step_size == 0:
                step_size = None

            if reference is not None:
                output_variable_names = reference.dtype.names[1:]
            else:
                output_variable_names = None

            try:
                start_time = time.time()

                # simulate the FMU
                result = fmpy.simulate_fmu(filename=fmu_filename,
                                           validate=False,
                                           step_size=step_size,
                                           stop_time=ref_opts['StopTime'],
                                           input=input,
                                           output=output_variable_names,
                                           timeout=None)

                sim_cell = '<td class="status"><span class="label label-success">%.2f s</span></td>' % (
                    time.time() - start_time)

            except Exception as e:
                sim_cell = '<td class="status"><span class="label label-danger" title="' + str(
                    e) + '">failed</span></td>'

        ##############
        # VALIDATION #
        ##############
        if skipped:
Esempio n. 3
0
def simulate(dpi=300, plotDirectory='plots'):
    # Set the comparison for dymola results

    dymolaComparisons = ['non-fmu-all', 'fmu-all', 'non-fmu', 'fmu']

    # In[3]:

    # Create plot directory
    # plotDirectory = 'plots'
    plotPath = plotDirectory
    if os.path.exists(plotPath):
        shutil.rmtree(plotPath)

    os.makedirs(plotPath)
    for key in dymolaComparisons:
        os.makedirs(os.path.join(plotPath, key))

    for dymolaComparison in dymolaComparisons:

        # # FMpy Library

        # In[4]:

        fmu_tests = ['Connectors', 'Inputs', 'Parameters']
        for fmu_test in fmu_tests:
            #     fmu_test = fmu_tests[0]
            fmu_path = '../FMUs/' + fmu_test + '/'
            fmu = fmu_path + 'FMIRaven_Models_LorenzSystem_' + fmu_test + '.fmu'

            # In[5]:

            fmpy.dump(fmu)

            # In[6]:

            model_description = fmpy.read_model_description(fmu)

            # In[7]:

            vrs = []
            for variable in model_description.modelVariables:
                vrs.append(variable.name)

            # In[8]:

            vrs

            # In[9]:

            outputs = ['x', 'y', 'z', 'sigma', 'beta', 'rho']
            start_values = {'sigma': 10, 'rho': 28, 'beta': 8 / 3}
            inputs = np.genfromtxt('input_test.txt', delimiter=',', names=True)
            result = fmpy.simulate_fmu(
                fmu, output=outputs, start_values=start_values
            )  #,input=inputs)         # simulate the FMU

            # In[10]:

            from fmpy.util import plot_result  # import the plot function
            # plot_result(result,names=outputs)

            fig, ax = plt.subplots(len(outputs), 1, figsize=[12, 12])
            for i, v in enumerate(outputs):
                ax[i].plot(result['time'], result[v])
                ax[i].set_ylabel(v, rotation=0, labelpad=20)

            fig.savefig(plotPath +
                        '/{}/{}_fmpy.png'.format(dymolaComparison, fmu_test),
                        dpi=dpi)

            # # pyFMI Library

            # In[11]:

            from pyfmi import load_fmu
            model = load_fmu(fmu)
            model.set('sigma', 10)
            model.set('beta', 8 / 3)
            model.set('rho', 28)
            res_pyfmi = model.simulate()

            # In[12]:

            fig, ax = plt.subplots(len(outputs), 1, figsize=[12, 12])
            for i, v in enumerate(outputs):
                ax[i].plot(res_pyfmi['time'], res_pyfmi[v])
                ax[i].set_ylabel(v, rotation=0, labelpad=20)

            fig.savefig(plotPath +
                        '/{}/{}_pyfmi.png'.format(dymolaComparison, fmu_test),
                        dpi=dpi)

            # # Dymola Result File

            # In[13]:

            from buildingspy.io.outputfile import Reader

            # In[14]:

            if dymolaComparison == 'non-fmu-all':
                dymResultPath = 'MATFiles/BasicTest.mat'
                modelName = fmu_test

            elif dymolaComparison == 'fmu-all':
                dymResultPath = 'MATFiles/FMU_BasicTest.mat'
                modelName = fmu_test

            elif dymolaComparison == 'non-fmu':
                dymResultPath = 'MATFiles/{}.mat'.format(fmu_test)
                modelName = 'fmu'

            elif dymolaComparison == 'fmu':
                dymResultPath = 'MATFiles/FMU_{}.mat'.format(fmu_test)
                modelName = 'fmu'

            else:
                raise ValueError('Unsported dymolaComparison')

            res = Reader(dymResultPath, simulator='dymola')

            # In[15]:

            res_dym = {}
            res_dym['time'], res_dym['x'] = res.values(
                '{}.x'.format(modelName))
            _, res_dym['y'] = res.values('{}.y'.format(modelName))
            _, res_dym['z'] = res.values('{}.z'.format(modelName))
            _, res_dym['sigma'] = res.values('{}.sigma'.format(modelName))
            _, res_dym['beta'] = res.values('{}.beta'.format(modelName))
            _, res_dym['rho'] = res.values('{}.rho'.format(modelName))

            # In[16]:

            fig, ax = plt.subplots(len(outputs), 1, figsize=[12, 12])
            for i, v in enumerate(outputs):
                try:
                    ax[i].plot(res_dym['time'], res_dym[v])
                    ax[i].set_ylabel(v, rotation=0, labelpad=20)
                except:
                    pass
            fig.savefig(plotPath +
                        '/{}/{}_dymola.png'.format(dymolaComparison, fmu_test),
                        dpi=dpi)

            # # Result Comparison

            # In[17]:

            fig, ax = plt.subplots(len(outputs), 1, figsize=[12, 12])
            for i, v in enumerate(outputs):
                ax[i].plot(result['time'], result[v], 'k-', label='FMpy')
                ax[i].plot(res_pyfmi['time'],
                           res_pyfmi[v],
                           'b--',
                           label='pyFMI')
                try:
                    ax[i].plot(res_dym['time'],
                               res_dym[v],
                               'r-.',
                               label='Dymola')
                except:
                    pass
                ax[i].legend()
                ax[i].set_ylabel(v, rotation=0, labelpad=20)

            fig.savefig(
                plotPath +
                '/{}/{}_comparison.png'.format(dymolaComparison, fmu_test),
                dpi=dpi)

            # # Diff between FMU and Dymola

            # In[18]:

            fig, ax = plt.subplots(len(outputs), 1, figsize=[12, 12])
            for i, v in enumerate(outputs):
                try:
                    ax[i].plot(result['time'],
                               result[v] - res_dym[v],
                               'k-',
                               label='FMpy - Dymola')
                    ax[i].plot(result['time'],
                               res_pyfmi[v] - res_dym[v],
                               'b--',
                               label='pyFMI - Dymola')
                except:
                    pass
                ax[i].legend()
                ax[i].set_ylabel(v, rotation=0, labelpad=20)

            fig.savefig(plotPath + '/{}/{}_diff_FMUtoDymola.png'.format(
                dymolaComparison, fmu_test),
                        dpi=dpi)

            # # Diff between FMUs

            # In[19]:

            fig, ax = plt.subplots(len(outputs), 1, figsize=[12, 12])
            for i, v in enumerate(outputs):
                try:
                    ax[i].plot(result['time'],
                               result[v] - res_pyfmi[v],
                               'k-',
                               label='FMpy - pyFMI')
                except:
                    pass
                ax[i].legend()
                ax[i].set_ylabel(v, rotation=0, labelpad=20)

            fig.savefig(
                plotPath +
                '/{}/{}_diff_FMUtoFMU.png'.format(dymolaComparison, fmu_test),
                dpi=dpi)

    plt.close('all')
Esempio n. 4
0
def main():

    import argparse
    import textwrap

    description = """\
    Validate and simulate Functional Mock-up Units (FMUs)

    Get information about an FMU:
       
        fmpy info Rectifier.fmu
     
    Simulate an FMU:
     
        fmpy simulate Rectifier.fmu --show-plot
        
    Compile a source code FMU:
    
        fmpy compile Rectifier.fmu
    """

    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description=textwrap.dedent(description))

    parser.add_argument('command',
                        choices=['info', 'simulate', 'compile'],
                        help="Command to execute")
    parser.add_argument('fmu_filename', help="filename of the FMU")

    parser.add_argument('--solver',
                        choices=['Euler', 'CVode'],
                        default='CVode',
                        help="solver to use for Model Exchange")
    parser.add_argument('--input-file', help="CSV file to use as input")
    parser.add_argument('--output-variables',
                        nargs='+',
                        help="Variables to record")
    parser.add_argument('--output-file', help="CSV to store the results")
    parser.add_argument('--num-samples',
                        default=500,
                        type=int,
                        help="number of samples to record")
    parser.add_argument('--step-size',
                        type=float,
                        help="step size for fixed-step solvers")
    parser.add_argument('--start-time',
                        type=float,
                        help="start time for the simulation")
    parser.add_argument('--stop-time',
                        type=float,
                        help="stop time for the simulation")
    parser.add_argument('--show-plot',
                        action='store_true',
                        help="plot the results")
    parser.add_argument('--timeout',
                        type=float,
                        help="max. time to wait for the simulation to finish")
    parser.add_argument('--fmi-logging',
                        action='store_true',
                        help="enable FMI logging")
    parser.add_argument('--start-values',
                        nargs='+',
                        help="name-value pairs of start values")

    args = parser.parse_args()

    if args.command == 'info':

        from fmpy import dump
        dump(args.fmu_filename)

    elif args.command == 'compile':

        from fmpy.util import compile_platform_binary
        compile_platform_binary(args.fmu_filename)

    elif args.command == 'simulate':

        from fmpy import simulate_fmu
        from fmpy.util import read_csv, write_csv, plot_result

        if args.start_values:
            if len(args.start_values) % 2 != 0:
                raise Exception("Start values must be name-value pairs.")
            start_values = {
                k: v
                for k, v in zip(args.start_values[::2],
                                args.start_values[1::2])
            }
        else:
            start_values = {}

        input = read_csv(args.input_file) if args.input_file else None

        result = simulate_fmu(args.fmu_filename,
                              validate=True,
                              start_time=args.start_time,
                              stop_time=args.stop_time,
                              solver=args.solver,
                              step_size=args.step_size,
                              output_interval=None,
                              fmi_type=None,
                              start_values=start_values,
                              input=input,
                              output=args.output_variables,
                              timeout=args.timeout,
                              fmi_logging=args.fmi_logging)

        if args.output_file:
            write_csv(filename=args.output_file, result=result)

        if args.show_plot:
            plot_result(result=result, window_title=args.fmu_filename)
Esempio n. 5
0
 def test_boolRef(self):
     filename = self.fmu_path('fmu_boolRef.fmu')
     result = fmpy.simulate_fmu(filename, start_values={'a': True})
     self.assertTrue(np.all(result['c'] != 0.0))
Esempio n. 6
0
 def test_illegal_fmi_type(self):
     with self.assertRaises(Exception) as context:
         simulate_fmu('CoupledClutches.fmu', fmi_type='Hybrid')
     self.assertEqual(
         'fmi_type must be one of "ModelExchange" or "CoSimulation"',
         str(context.exception))
Esempio n. 7
0
    print(model_name)
    fmu = os.path.join(dist_dir, model_name + '.fmu')

    ref_csv = os.path.join(src_dir, model_name, model_name + '_ref.csv')
    ref_png = os.path.join(src_dir, model_name, model_name + '_ref.svg')
    in_csv  = os.path.join(src_dir, model_name, model_name + '_in.csv')

    if os.path.isfile(in_csv):
        input = read_csv(in_csv)
    else:
        input = None

    result = simulate_fmu(fmu,
                          fmi_type='ModelExchange',
                          # solver='Euler',
                          start_values=start_values,
                          input=input,
                          output_interval=output_interval
                          )

    write_csv(ref_csv, result)
    ref = read_csv(ref_csv)
    plot_result(ref, events=True, filename=ref_png)

    md_file = os.path.join(src_dir, model_name, 'readme.md')
    html_file = os.path.join(src_dir, model_name, 'readme.html')

    md = markdown2.markdown_path(md_file, extras=['tables', 'fenced-code-blocks'])

    with open(html_file, 'w') as html:
        html.write(header1)
Esempio n. 8
0
 def test_variablesRef(self):
     filename = self.fmu_path('fmu_variablesRef.fmu')
     result = fmpy.simulate_fmu(filename, output=['h'])
     self.assertTrue(np.all(result['h'] <= 1.0))
Esempio n. 9
0
 def test_verRef(self):
     filename = self.fmu_path('fmu_verRef.fmu')
     with self.assertRaises(Exception) as context:
         fmpy.simulate_fmu(filename)
     self.assertEquals(context.exception.message, 'Unsupported FMI version: 2.0.1')
Esempio n. 10
0
 def test_stringParamRef(self):
     filename = self.fmu_path('fmu_stringParamRef.fmu')
     result = fmpy.simulate_fmu(filename, start_values={'str_a_': 'string PARAMETER!'}, output=['int_c_'])
     self.assertTrue(np.all(result['int_c_'] == 1))
Esempio n. 11
0
 def test_tEventRef(self):
     filename = self.fmu_path('fmu_tEventRef.fmu')
     result = fmpy.simulate_fmu(filename, stop_time=1.5, output=['a_'])
     self.assertTrue(result['a_'][-1] == 1)
Esempio n. 12
0
 def test_integerRef(self):
     filename = self.fmu_path('fmu_integerRef.fmu')
     result = fmpy.simulate_fmu(filename, start_values={'a': 2, 'b': 3}, output=['c'])
     self.assertTrue(np.all(result['c'] == 5))
Esempio n. 13
0
 def test_DLLRef_64(self):
     filename = self.fmu_path('fmu_DLLRef_64.fmu')
     result = fmpy.simulate_fmu(filename, start_values={'a_': 2.0}, output=['b_'])
     self.assertTrue(np.all(result['b_'] == 4.0))
Esempio n. 14
0
 def test_csvRef(self):
     filename = self.fmu_path('fmu_csvRef.fmu')
     result = fmpy.simulate_fmu(filename, output=['b_'])
     self.assertTrue(np.all(result['b_'] == 9))
Esempio n. 15
0
def simulate_direct(fmu, t0, t1, pars):
    return fmpy.simulate_fmu(fmu, start_time=t0, stop_time=t1,
                             start_values=pars, **simargs)
Esempio n. 16
0
    def test_create_fmu_container(self):

        examples = os.path.join(os.environ['SSP_STANDARD_DEV'],
                                'SystemStructureDescription', 'examples')

        configuration = {

            # description of the container
            'description':
            'A controlled drivetrain',

            # optional dictionary to customize attributes of exposed variables
            'variables': {
                'controller.PI.k': {
                    'name': 'k'
                },
                'controller.u_s': {
                    'name': 'w_ref',
                    'description': 'Reference speed'
                },
                'drivetrain.w': {
                    'name': 'w',
                    'description': 'Motor speed'
                },
            },

            # models to include in the container
            'components': [
                {
                    'filename':
                    os.path.join(examples,
                                 'Controller.fmu'),  # filename of the FMU
                    'name': 'controller',  # instance name
                    'variables':
                    ['u_s', 'PI.k']  # variables to expose in the container
                },
                {
                    'filename': os.path.join(examples, 'Drivetrain.fmu'),
                    'name': 'drivetrain',
                    'variables': ['w']
                }
            ],

            # connections between the FMU instances
            'connections': [
                # <from_instance>, <from_variable>, <to_instance>, <to_variable>
                ('drivetrain', 'w', 'controller', 'u_m'),
                ('controller', 'y', 'drivetrain', 'tau'),
            ]
        }

        filename = 'ControlledDrivetrain.fmu'

        create_fmu_container(configuration, filename)

        w_ref = np.array([(0.5, 0), (1.5, 1), (2, 1), (3, 0)],
                         dtype=[('time', 'f8'), ('w_ref', 'f8')])

        result = simulate_fmu(filename,
                              start_values={'k': 20},
                              input=w_ref,
                              output=['w_ref', 'w'],
                              stop_time=4)
Esempio n. 17
0
    def doFunc(self):

        inputValues = []
        FMUinputRefs = []
        if self.inType == VALUETYPES.REAL:
            #            for i in range(0, len(self.input)):
            #                if self.options['inmask'][i] == 0:  # The mask vector is used to separate initialization inputs (inmask=1) from regular causality="input" (inmask=0)
            for i in range(0, len(self.options['inputs'])):
                inputValues.append(self.input[i]['value'])
                FMUinputRefs.append(self.FMUinput[i])

        else:
            print(
                "This function is not supported yet!"
            )  # figure out how to initialize fmu when the entire input vector is given

        self.myFMU.setReal(list(FMUinputRefs), list(inputValues))
        #        self.myFMU.setReal(list(self.FMUinput), list(inputValues))

        if self.options[
                'dyn'] == 'full':  #TODO: probably need to change all self.options['inputs'] into combination of self.options['inputs'] and self.options['x0']

            # setup the numpy format for specifying input variables
            dt = [('time', np.float64)]
            dt += zip(self.options['inputs'],
                      [np.float64] * len(self.options['inputs']))

            # print the numpy format for specifying input variables just to make sure it's ok
            print(dt)

            # assign the input to input variables
            #    pom = numpy.empty(len(inputValues),dtype=dt)
            if self.options['type'] == "ME":
                pom = numpy.empty(
                    2, dtype=dt
                )  # with ME it is necessary to assign first step value and last step value
                pom['time'] = [self.Tstart, self.Tstop]
            elif self.options['type'] == 'CS':
                pom = numpy.empty(
                    1, dtype=dt
                )  # with CS it is necessary just to assign one value for the entire period
                pom['time'] = self.Tstart

            for i in range(0, len(self.options['inputs'])):
                pom[self.options['inputs'][i]] = inputValues[
                    i]  # assign all input values, time has been assigned previously

            print(pom)
            inputValues = pom

            result = simulate_fmu(self.options['fmu'],
                                  start_time=self.Tstart,
                                  stop_time=self.Tstop,
                                  timeout=self.Timeout,
                                  step_size=self.Tstep,
                                  input=inputValues,
                                  output=self.options['outputs'])
            print("result of simulate_fmu is " + str(result))
            print("dtype is " + str(result.dtype))

            for i in range(0, len(self.options['outputs'])):
                pom = result[self.options['outputs'][i]]
                print(pom)
                if self.outType == VALUETYPES.REAL:
                    self.output[i]['value'] = pom[-1]
                elif self.outType == VALUETYPES.VECTOR:
                    self.output[i]['value'] = pom

        elif self.options['dyn'] == 'step':

            time = self.time
            if self.options['type'] == 'CS':
                self.inEvent.apply(time)
                self.myFMU.doStep(currentCommunicationPoint=time,
                                  communicationStepSize=self.Tstep)
                self.time += self.Tstep
            elif self.options['type'] == 'ME':
                eps = 1.0e-13
                # step ahead in time
                if self.fixed_step:
                    if time + self.Tstep < self.Tstop + eps:
                        self.t_next = time + self.Tstep
                        #            else:
                        #                break
                else:
                    if time + eps >= self.t_next:  # t_next has been reached
                        # integrate to the next grid point
                        self.t_next = round(
                            time / self.Tstep) * self.Tstep + self.Tstep

                # gets the time of input event
                t_input_event = self.inEvent.apply(time)

                # check for input event
                input_event = t_input_event <= self.t_next

                if input_event:
                    self.t_next = t_input_event

                # check the time of next event.
                time_event = None
                if self.options['fmu_ver'] == 1:
                    time_event = self.myFMU.eventInfo.upcomingTimeEvent != fmi1False and self.myFMU.eventInfo.nextEventTime <= self.t_next
                elif self.options['fmu_ver'] == 2:
                    time_event = self.myFMU.eventInfo.nextEventTimeDefined != fmi2False and self.myFMU.eventInfo.nextEventTime <= self.t_next
                else:
                    Exception("Please provide an existing FMU version")

                if time_event and not self.fixed_step:
                    self.t_next = self.myFMU.eventInfo.nextEventTime

                state_event = None
                if self.t_next - time > eps:
                    # do one step
                    state_event, time = self.solver.step(time, self.t_next)
                else:
                    # skip
                    time = self.t_next

                # set the time
                self.myFMU.setTime(time)

                # check for step event, e.g.dynamic state selection
                step_event = None
                if self.options['fmu_ver'] == 1:
                    step_event = self.myFMU.completedIntegratorStep()
                elif self.options['fmu_ver'] == 2:
                    step_event, _ = self.myFMU.completedIntegratorStep()
                    step_event = step_event != fmi2False
                else:
                    Exception("Please provide an existing FMU version")

                # handle events
                if input_event or time_event or state_event or step_event:

                    # recorder.sample(time, force=True)

                    if input_event:
                        self.inEvent.apply(time=time, after_event=True)

                    # handle events
                    if self.options['fmu_ver'] == 1:
                        self.myFMU.eventUpdate()
                    elif self.options['fmu_ver'] == 2:
                        # handle events
                        self.myFMU.enterEventMode()

                        self.myFMU.eventInfo.newDiscreteStatesNeeded = fmi2True
                        self.myFMU.eventInfo.terminateSimulation = fmi2False

                        # update discrete states
                        while self.myFMU.eventInfo.newDiscreteStatesNeeded != fmi2False and self.myFMU.eventInfo.terminateSimulation == fmi2False:
                            self.myFMU.newDiscreteStates()

                        self.myFMU.enterContinuousTimeMode()
                    else:
                        Exception("Please provide an existing FMU version")

                    self.solver.reset(time)
            else:
                Exception("Please provide either 'ME' or 'CS' type.")

            pom = self.myFMU.getReal(list(self.FMUoutput))
            for i in range(0, len(self.FMUoutput)):
                self.output[i]['value'] = pom[i]

            print(pom)
        else:
            Exception(
                "Simulation option 'dyn' can be either 'step' or 'full'.")
Esempio n. 18
0
    def simulate(self, reset=True):
        """Performs a simulation.

        :param bool reset: if True, the model will be resetted after
                           simulation (use False with E+ FMU)
        :return: Dataframe with results
        """
        # Calculate output interval (in seconds)
        assert self.input_arr is not None, "No inputs assigned"
        output_interval = self.input_arr[1][0] - self.input_arr[0][0]

        # Initial condition
        start_values = dict()
        input_names = self.input_arr.dtype.names
        for name in input_names:
            if name != "time":
                start_values[name] = self.input_arr[name][0]

        assert "time" in input_names, "time must be the first input"

        # Set parameters
        for name, value in self.parameters.items():
            if name != "time":
                start_values[name] = value

        # Inputs
        assert self.input_arr is not None, "Inputs not assigned!"

        # Options (fixed)
        pass  # TODO

        # Options (user)
        pass  # TODO

        # Simulation
        self.logger.debug("Starting simulation")
        result = simulate_fmu(
            self.unzipdir,
            start_values=start_values,
            start_time=self.start,
            stop_time=self.end,
            input=self.input_arr,
            output=self.output_names,
            output_interval=output_interval,
            fmu_instance=self.model
            # solver='Euler',  # TODO: It might be useful to add solver/step to options
            # step_size=0.005
        )

        # Convert result to DataFrame
        res_df = struct_arr_to_df(result)

        # Reset model
        if reset:
            try:
                self.model.reset()
            except Exception as e:
                self.logger.warning(str(e))
                self.logger.warning(
                    "If you try to simulate an EnergyPlus FMU, "
                    "use reset=False")
        # Return
        return res_df
Esempio n. 19
0
 def test_unsupported_fmi_type(self):
     with self.assertRaises(Exception) as context:
         simulate_fmu('CoupledClutches.fmu', fmi_type='CoSimulation')
     self.assertEqual('FMI type "CoSimulation" is not supported by the FMU',
                      str(context.exception))
Esempio n. 20
0
# test FMPy optim
import fmpy

fmu = 'ADAN_0main_SystemicTree_Tilt_OlufsenTriSeg_0tiltable.fmu'

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',
                                    fmi_call_logger=lambda s: print(s),
                                    debug_logging=True)

# the python breaks at fmu.terminate()
result = fmpy.simulate_fmu(unzipdir,
                           fmu_instance=fmu_instance,
                           stop_time=1,
                           relative_tolerance=1e-6,
                           output_interval=0.02)

# it wont come to this point without any trace
print(result)
fmpy.write_csv('test', result)
pass
Esempio n. 21
0
    def test_step_size_me(self):

        # download the FMU and input file
        for filename in ['CoupledClutches.fmu', 'CoupledClutches_in.csv']:
            download_test_file('2.0', 'me', 'MapleSim', '2016.2',
                               'CoupledClutches', filename)

        # load the input
        input = np.genfromtxt('CoupledClutches_in.csv',
                              delimiter=',',
                              names=True)

        self.assertTrue(np.sum(input['time'] == 0.9) > 1,
                        msg="Input event expected at t=0.9")

        start_time = 0.0
        stop_time = 1.5
        step_size = 1e-2
        output_interval = 2e-2
        T2 = 0.5

        # common arguments
        kwargs = {
            'filename': 'CoupledClutches.fmu',
            'start_time': start_time,
            'stop_time': stop_time,
            'fmi_type': 'ModelExchange',
            'step_size': step_size,
            'output_interval': output_interval,
            'input': input,
            'start_values': {
                'CoupledClutches1_T2': T2
            }
        }

        # fixed step w/o events
        result = simulate_fmu(solver='Euler', record_events=False, **kwargs)

        time = result['time']
        self.assertAlmostEqual(
            time[0],
            start_time,
            msg="First sample time must be equal to start_time")
        self.assertAlmostEqual(
            time[-1],
            stop_time,
            msg="Last sample time must be equal to stop_time")
        self.assertTrue(np.all(np.isclose(np.diff(time), output_interval)),
                        msg="Output intervals must be regular")

        # fixed step w/ events
        result = simulate_fmu(solver='Euler', record_events=True, **kwargs)

        time = result['time']
        self.assertAlmostEqual(
            time[0],
            start_time,
            msg="First sample time must be equal to start_time")
        self.assertAlmostEqual(
            time[-1],
            stop_time,
            msg="Last sample time must be equal to stop_time")

        # variable step w/o events
        result = simulate_fmu(solver='CVode', record_events=False, **kwargs)

        time = result['time']
        self.assertAlmostEqual(
            time[0],
            start_time,
            msg="First sample time must be equal to start_time")
        self.assertAlmostEqual(
            time[-1],
            stop_time,
            msg="Last sample time must be equal to stop_time")
        steps = np.diff(time)
        steps = steps[steps > 1e-13]  # remove events
        self.assertTrue(np.all(np.isclose(steps, output_interval)),
                        msg="Output intervals must be regular")

        # variable step w/ events
        result = simulate_fmu(solver='CVode', record_events=True, **kwargs)

        time = result['time']
        self.assertAlmostEqual(
            time[0],
            start_time,
            msg="First sample time must be equal to start_time")
        self.assertAlmostEqual(
            time[-1],
            stop_time,
            msg="Last sample time must be equal to stop_time")
        self.assertTrue(np.sum(time == 0.9) > 1,
                        msg="Input event expected at t=0.9")
        self.assertTrue(np.sum(np.isclose(time, T2)) > 1,
                        msg="Time event expected at t=T2")
Esempio n. 22
0
    def simulate(self, udf, x0, save_state=False):
        """
        Simulate the model using the provided inputs `udf`
        and initial state `x0`.
        The DataFrame should have the following content:
        - index - time in seconds and equal steps, named 'time',
        - columns - input data,
        - column names - input variable names.
        The order of `x0` should reflect the one used in `states`.
        Return two DataFrames, `ydf` and `xdf`, with
        outputs and states, respectively, and with the same
        structure as `udf`.
        :param udf: DataFrame, shape (n_steps, n_variables)
        :param x0: vector, size (n_states, )
        :return: ydf, xdf
        """
        assert udf.index.name == 'time'

        timeline = udf.index.values
        start = timeline[0]
        stop = timeline[-1]

        # Prepare inputs for fmpy:
        input_arr = df_to_struct_arr_new(udf)
        assert input_arr is not None, "No inputs assigned"
        output_interval = input_arr[1][0] - input_arr[0][0]

        # Initial condition
        start_values = dict()
        input_names = input_arr.dtype.names
        for name in input_names:
            if name != 'time':
                start_values[name] = input_arr[name][0]

        assert 'time' in input_names, "time must be the first input"

        # Set parameters
        for name, value in self.parameters.items():
            if name != 'time':
                start_values[name] = value

        # Initial states overriden by the user
        i = 0
        for n in self.states:
            start_values[n] = x0[i]
            i += 1

        # Simulate
        if not self.verbose:
            nullf = open(os.devnull, 'w')
            sys.stdout = nullf

        self.output_names = list(self.outputs)
        #derivative_names = [der.variable.name for der in self.model_description.derivatives]
        # names = [re.search(r'der\((.*)\)', n).group(1) for n in derivative_names]
        #for name in derivative_names:
        #self.output_names.append(name)
        for name in self.states:
            self.output_names.append(name)

        res = simulate_fmu(
            self.unzipdir,
            start_values=start_values,
            start_time=start,
            stop_time=stop,
            input=input_arr,
            output=self.output_names,
            output_interval=output_interval,
            fmu_instance=self.fmu
            # solver='Euler',  # TODO: It might be useful to add solver/step to options
            # step_size=0.005
        )
        #states = self.fmu.getFMUstate()

        if not self.verbose:
            sys.stdout = sys.__stdout__
            nullf.close()

        # Update state (use only in emulation)
        if save_state:
            self.x0 = self._get_state()

        # Outputs
        res_df = struct_arr_to_df(res)
        ydf = pd.DataFrame()
        xdf = pd.DataFrame()

        for n in self.outputs:
            ydf[n] = res_df[n]

        for n in self.states:
            xdf[n] = res_df[n]

        self.fmu.reset()

        return ydf, xdf
Esempio n. 23
0
def main():

    import argparse
    import textwrap

    description = """\
    Validate and simulate Functional Mock-up Units (FMUs)

    Get information about an FMU:
       
        fmpy info Rectifier.fmu
     
    Simulate an FMU:
     
        fmpy simulate Rectifier.fmu --show-plot
        
    Compile a source code FMU:
    
        fmpy compile Rectifier.fmu
        
    Create a Jupyter Notebook
    
        fmpy create-jupyter-notebook Rectifier.fmu
    """

    parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
                                     description=textwrap.dedent(description))

    parser.add_argument('command', choices=['info', 'validate', 'simulate', 'compile', 'add-cswrapper', 'add-remoting',
                                            'create-cmake-project', 'create-jupyter-notebook'],
                        help="Command to execute")
    parser.add_argument('fmu_filename', help="filename of the FMU")

    parser.add_argument('--validate', action='store_true', help="validate the FMU")
    parser.add_argument('--start-time', type=float, help="start time for the simulation")
    parser.add_argument('--stop-time', type=float, help="stop time for the simulation")
    parser.add_argument('--solver', choices=['Euler', 'CVode'], default='CVode', help="solver to use for Model Exchange")
    parser.add_argument('--step-size', type=float, help="step size for fixed-step solvers")
    parser.add_argument('--relative-tolerance', type=float, help="relative tolerance for the 'CVode' solver and FMI 2.0 co-simulation FMUs")
    parser.add_argument('--dont-record-events', action='store_true', help="dont't record outputs at events (model exchange only)")
    parser.add_argument('--start-values', nargs='+', help="name-value pairs of start values")
    parser.add_argument('--apply-default-start-values', action='store_true', help="apply the start values from the model description")
    parser.add_argument('--output-interval', type=float, help="interval for sampling the output")
    parser.add_argument('--input-file', help="CSV file to use as input")
    parser.add_argument('--output-variables', nargs='+', help="Variables to record")
    parser.add_argument('--output-file', help="CSV to store the results")
    parser.add_argument('--timeout', type=float, help="max. time to wait for the simulation to finish")
    parser.add_argument('--debug-logging', action='store_true', help="enable the FMU's debug logging")
    parser.add_argument('--visible', action='store_true', help="enable interactive mode")
    parser.add_argument('--fmi-logging', action='store_true', help="enable FMI logging")
    parser.add_argument('--show-plot', action='store_true', help="plot the results")
    parser.add_argument('--cmake-project-dir', help="Directory for the CMake project")

    args = parser.parse_args()

    if args.command == 'info':

        from fmpy import dump
        dump(args.fmu_filename)

    elif args.command == 'validate':

        import sys
        from fmpy.validation import validate_fmu

        problems = validate_fmu(args.fmu_filename)

        if len(problems) == 0:
            print('No problems found.')
        else:
            print('%d problems were found:' % len(problems))
            for message in problems:
                print()
                print(message)

        sys.exit(len(problems))

    elif args.command == 'compile':

        from fmpy.util import compile_platform_binary
        compile_platform_binary(args.fmu_filename)

    elif args.command == 'add-cswrapper':

        from fmpy.cswrapper import add_cswrapper
        add_cswrapper(args.fmu_filename)

    elif args.command == 'add-remoting':

        from fmpy.util import add_remoting
        add_remoting(args.fmu_filename)

    elif args.command == 'create-cmake-project':

        import os
        from fmpy.util import create_cmake_project

        project_dir = args.cmake_project_dir

        if project_dir is None:
            project_dir = os.path.basename(args.fmu_filename)
            project_dir, _ = os.path.splitext(project_dir)
            print("Creating CMake project in %s" % os.path.abspath(project_dir))

        create_cmake_project(args.fmu_filename, project_dir)

    elif args.command == 'create-jupyter-notebook':

        from fmpy.util import create_jupyter_notebook

        create_jupyter_notebook(args.fmu_filename)

    elif args.command == 'simulate':

        from fmpy import simulate_fmu
        from fmpy.util import read_csv, write_csv, plot_result

        if args.start_values:
            if len(args.start_values) % 2 != 0:
                raise Exception("Start values must be name-value pairs.")
            start_values = {k: v for k, v in zip(args.start_values[::2], args.start_values[1::2])}
        else:
            start_values = {}

        input = read_csv(args.input_file) if args.input_file else None

        if args.fmi_logging:
            fmi_call_logger = lambda s: print('[FMI] ' + s)
        else:
            fmi_call_logger = None

        result = simulate_fmu(args.fmu_filename,
                              validate=args.validate,
                              start_time=args.start_time,
                              stop_time=args.stop_time,
                              solver=args.solver,
                              step_size=args.step_size,
                              relative_tolerance=args.relative_tolerance,
                              output_interval=args.output_interval,
                              record_events=not args.dont_record_events,
                              fmi_type=None,
                              start_values=start_values,
                              apply_default_start_values=args.apply_default_start_values,
                              input=input,
                              output=args.output_variables,
                              timeout=args.timeout,
                              debug_logging=args.debug_logging,
                              visible=args.visible,
                              fmi_call_logger=fmi_call_logger)

        if args.output_file:
            write_csv(filename=args.output_file, result=result)

        if args.show_plot:
            plot_result(result=result, window_title=args.fmu_filename)
Esempio n. 24
0
dahl = 'Dahlquist1.fmu'
#fmpy.dump(dahl)
#results=fmpy.simulate_fmu(dahl)
#results=fmpy.simulate_fmu(dahl,start_values={'x':3})
#l =['hello',1.0,2];
#print(l[0])
#l.append('bye')
result = []
xStart = [i for i in range(11)]
#list_a = list(range(11))
#len(xStart)==len(list_a)

for i in xStart:
    rs = fmpy.simulate_fmu(dahl,
                           start_values={'x': i},
                           start_time=0,
                           stop_time=5)
    result.append(rs)

for j in range(11):
    plt.plot(result[j]['time'], result[j]['x'])

plt.xlabel("Time (s)")
plt.ylabel("x")
plt.grid(color='grey', linestyle='-', linewidth=2)
kValues = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
plt.legend(kValues)

#dtype <f8 -> little-endian single-precision float
#result[0].dtype.kind 'V'-> raw data