# 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()
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:
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')
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)
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))
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))
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)
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))
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')
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))
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)
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))
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))
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))
def simulate_direct(fmu, t0, t1, pars): return fmpy.simulate_fmu(fmu, start_time=t0, stop_time=t1, start_values=pars, **simargs)
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)
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'.")
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
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))
# 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
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")
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
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)
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