def test_step_size(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") self.assertTrue(np.all(np.isclose(np.diff(time), 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 test_get_directional_derivative(self): fmu_filename = 'Rectifier.fmu' download_test_file('2.0', 'CoSimulation', 'Dymola', '2017', 'Rectifier', fmu_filename) model_description = read_model_description(filename=fmu_filename) unzipdir = extract(fmu_filename) fmu = FMU2Slave( guid=model_description.guid, unzipDirectory=unzipdir, modelIdentifier=model_description.coSimulation.modelIdentifier) fmu.instantiate() fmu.setupExperiment() fmu.enterInitializationMode() # get the partial derivative for an initial unknown unknown = model_description.initialUnknowns[1] self.assertEqual('iAC[1]', unknown.variable.name) vrs_unknown = [unknown.variable.valueReference] vrs_known = [v.valueReference for v in unknown.dependencies] dv_known = [1.0] * len(unknown.dependencies) partial_der = fmu.getDirectionalDerivative(vUnknown_ref=vrs_unknown, vKnown_ref=vrs_known, dvKnown=dv_known) self.assertEqual([-2.0], partial_der) fmu.exitInitializationMode() # get the partial derivative for three output variables unknowns = model_description.outputs[4:7] self.assertEqual(['uAC[1]', 'uAC[2]', 'uAC[3]'], [u.variable.name for u in unknowns]) vrs_unknown = [u.variable.valueReference for u in unknowns] vrs_known = [v.valueReference for v in unknowns[0].dependencies] dv_known = [1.0] * len(vrs_known) partial_der = fmu.getDirectionalDerivative(vUnknown_ref=vrs_unknown, vKnown_ref=vrs_known, dvKnown=dv_known) self.assertAlmostEqual(-1500, partial_der[0]) self.assertAlmostEqual(0, partial_der[1]) self.assertAlmostEqual(1500, partial_der[2]) fmu.terminate() fmu.freeInstance() rmtree(unzipdir)
def setUpClass(cls): # download the FMU and input file download_test_file('2.0', 'ModelExchange', 'MapleSim', '2016.2', 'CoupledClutches', 'CoupledClutches.fmu') download_test_file('2.0', 'ModelExchange', 'MapleSim', '2016.2', 'CoupledClutches', 'CoupledClutches_in.csv') download_file( 'https://github.com/modelica/fmi-cross-check/raw/master/fmus/2.0/me/win64/Dymola/2019FD01/Rectifier/Rectifier.fmu' )
def test_cswrapper(self): filename = 'CoupledClutches.fmu' download_test_file('2.0', 'ModelExchange', 'MapleSim', '2016.2', 'CoupledClutches', filename) model_description = read_model_description(filename) self.assertIsNone(model_description.coSimulation) add_cswrapper(filename) simulate_fmu(filename, fmi_type='CoSimulation')
def test_create_juypter_notebook(self): download_test_file('2.0', 'ModelExchange', 'MapleSim', '2016.2', 'CoupledClutches', 'CoupledClutches.fmu') create_jupyter_notebook('CoupledClutches.fmu') args = [ 'jupyter', 'nbconvert', '--to', 'notebook', '--execute', '--ExecutePreprocessor.timeout=60', '--output', 'CoupledClutches_out.ipynb', 'CoupledClutches.ipynb' ] check_call(args)
def test_serialize_fmu_state(self): fmu_filename = 'Rectifier.fmu' # download the FMU download_test_file('2.0', 'cs', 'MapleSim', '2016.2', 'Rectifier', fmu_filename) # read the model description model_description = read_model_description(fmu_filename) # extract the FMU unzipdir = extract(fmu_filename) # instantiate the FMU fmu = FMU2Slave( guid=model_description.guid, unzipDirectory=unzipdir, modelIdentifier=model_description.coSimulation.modelIdentifier) # initialize fmu.instantiate() fmu.setupExperiment() fmu.enterInitializationMode() fmu.exitInitializationMode() # get the FMU state state = fmu.getFMUstate() # serialize the FMU state serialized_state = fmu.serializeFMUstate(state) # de-serialize the FMU state fmu.deSerializeFMUstate(serialized_state, state) # set the FMU state fmu.setFMUstate(state) # free the FMU state fmu.freeFMUstate(state) fmu.terminate() fmu.freeInstance() # clean up shutil.rmtree(unzipdir)
def test_extracted_fmu(self): """ Simulate an extracted FMU """ download_test_file('2.0', 'cs', 'MapleSim', '2016.2', 'CoupledClutches', 'CoupledClutches.fmu') # extract the FMU tempdir = extract('CoupledClutches.fmu') # load the model description before the simulation model_description = read_model_description(tempdir) result = simulate_fmu(tempdir, model_description=model_description) self.assertIsNotNone(result) # clean up shutil.rmtree(tempdir)
def test_get_start_values(self): if platform.startswith('win'): fmi_versions = ['2.0'] # quick fix until FMUs are available elif platform.startswith(('darwin', 'linux')): fmi_versions = ['2.0'] else: self.fail('Platform not supported') for fmi_version in fmi_versions: for fmi_type in ['CoSimulation', 'ModelExchange']: download_test_file(fmi_version, fmi_type, 'MapleSim', '2016.2', 'CoupledClutches', 'CoupledClutches.fmu') start_values = get_start_values('CoupledClutches.fmu') self.assertEqual(start_values['CoupledClutches1_freqHz'], '0.2')
def test_validate_start_values(self): filename = download_test_file('2.0', 'ModelExchange', 'MapleSim', '2016.2', 'CoupledClutches', 'CoupledClutches.fmu') with self.assertRaises(Exception) as context: simulate_fmu(filename, start_values={'clutch1.sa': 0.0}) self.assertEqual( 'The start values for the following variables could not be set: clutch1.sa', str(context.exception))
def simulate_coupled_clutches( fmi_version='2.0', fmi_type='ModelExchange', output=['outputs[1]', 'outputs[2]', 'outputs[3]', 'outputs[4]'], solver='CVode', fmi_logging=False, show_plot=True): # download the FMU and input file for filename in ['CoupledClutches.fmu', 'CoupledClutches_in.csv']: download_test_file(fmi_version, fmi_type, 'MapleSim', '2016.2', 'CoupledClutches', filename) print("Loading input...") input = np.genfromtxt('CoupledClutches_in.csv', delimiter=',', names=True) print("Simulating CoupledClutches.fmu (FMI %s, %s, %s)..." % (fmi_version, fmi_type, solver)) result = simulate_fmu(filename='CoupledClutches.fmu', start_time=0, stop_time=1.5, solver=solver, step_size=1e-2, output_interval=2e-2, start_values={'CoupledClutches1_freqHz': 0.4}, input=input, output=output, validate=False, fmi_logging=fmi_logging) if show_plot: print("Plotting results...") from fmpy.util import plot_result plot_result(result=result, window_title="CoupledClutches.fmu (FMI %s, %s, %s)" % (fmi_version, fmi_type, solver)) print("Done.") return result
def setUpClass(cls): # download the FMU download_test_file('2.0', 'me', 'MapleSim', '2016.2', 'CoupledClutches', 'CoupledClutches.fmu')
def setUpClass(cls): # download the FMU and input file download_test_file('2.0', 'ModelExchange', 'MapleSim', '2016.2', 'CoupledClutches', 'CoupledClutches.fmu') download_test_file('2.0', 'ModelExchange', 'MapleSim', '2016.2', 'CoupledClutches', 'CoupledClutches_in.csv')
def run_experiment(show_plot=True): if platform not in ['win32', 'win64']: raise Exception("Rectifier.fmu is only available for Windows") print("Parameter variation on %s:" % fmu_filename) print(" VAC", v_ac) print(" IDC", i_dc) if sync: dask.set_options( get=dask.dask.local.get_sync) # synchronized scheduler # download the FMU download_test_file('2.0', 'CoSimulation', 'Dymola', '2017', 'Rectifier', fmu_filename) # read the model description model_description = read_model_description(fmu_filename) # collect the value references for the variables to read / write vrs = {} for variable in model_description.modelVariables: vrs[variable.name] = variable.valueReference # extract the FMU unzipdir = fmpy.extract(fmu_filename) fmu_args = { 'guid': model_description.guid, 'modelIdentifier': model_description.coSimulation.modelIdentifier, 'unzipDirectory': unzipdir } # get the value references for the start and output values start_vrs = [vrs['VAC'], vrs['IDC']] result_vrs = [vrs['uDC'], vrs['Losses']] indices = list(np.ndindex(I_DC.shape)) chunks = [] chunk_size = int(np.ceil(len(indices) / 10)) # split the indices into 10 chunks for i in range(0, len(indices), chunk_size): chunks.append( [indices[i:i + chunk_size], fmu_args, start_vrs, result_vrs]) print("Running %d simulations (%d chunks)..." % (V_AC.size, len(chunks))) with ProgressBar(): # calculate the losses for every chunk results = bag.from_sequence(chunks).map(simulate_fmu).compute() LOSSES = np.zeros_like(V_AC) # put the results together for zipped, dll_handle in results: for i, res in zipped: LOSSES[i] = res[1] # unload the shared library if sync: while True: try: fmpy.freeLibrary(dll_handle) except: break # clean up shutil.rmtree(unzipdir) if show_plot: print("Plotting results...") import matplotlib.pyplot as plt figure = plt.figure() figure.patch.set_facecolor('white') ax = figure.add_subplot(1, 1, 1) CS = plt.contourf(V_AC, I_DC, LOSSES, 10) plt.colorbar(CS, aspect=30) CS = ax.contour(V_AC, I_DC, LOSSES, 10, colors='k', linewidths=0.8) ax.clabel(CS=CS, fmt='%.0f', fontsize=9, inline=1) ax.set_title('Losses / W') ax.set_xlabel('AC Voltage / V') ax.set_ylabel('DC Current / A') plt.show() else: print("Plotting disabled") print("Done.") return LOSSES
def test_common_functions(self): if platform.startswith('win'): fmi_versions = ['1.0', '2.0'] else: return for fmi_version in fmi_versions: model_name = 'BooleanNetwork1' filename = model_name + '.fmu' download_test_file(fmi_version, 'CoSimulation', 'Dymola', '2017', model_name, filename) model_description = read_model_description(filename) unzipdir = extract(filename) guid = model_description.guid variables = {} for v in model_description.modelVariables: variables[v.name] = v args = { 'guid': guid, 'modelIdentifier': model_description.coSimulation.modelIdentifier, 'unzipDirectory': unzipdir, 'instanceName': None } if fmi_version == '1.0': fmu = FMU1Slave(**args) fmu.instantiate("instance1") fmu.initialize() else: fmu = FMU2Slave(**args) fmu.instantiate(loggingOn=False) fmu.setupExperiment(tolerance=None) fmu.enterInitializationMode() fmu.exitInitializationMode() # get types platform types_platform = fmu.getTypesPlatform() if fmi_version == '1.0': self.assertEqual('standard32', types_platform) else: self.assertEqual('default', types_platform) # get FMI version version = fmu.getVersion() self.assertEqual(fmi_version, version) # set debug logging if fmi_version == '1.0': fmu.setDebugLogging(True) else: fmu.setDebugLogging(True, ['logAll']) # set and get Real vr = [variables['booleanPulse1.width'].valueReference] value = [30.0] fmu.setReal(vr, value) result = fmu.getReal(vr) self.assertTrue(result[0] == value[0]) # set and get Integer vr = [variables['integerConstant.k'].valueReference] value = [-4] fmu.setInteger(vr, value) result = fmu.getInteger(vr) self.assertTrue(result[0] == value[0]) # set and get Boolean vr = [variables['rSFlipFlop.Qini'].valueReference] value = [True] fmu.setBoolean(vr, value) result = fmu.getBoolean(vr) self.assertTrue(result[0] == value[0]) # TODO: set and get String # clean up fmu.terminate() fmu.freeInstance() shutil.rmtree(unzipdir)
def simulate_custom_input(show_plot=True): # define the model name and simulation parameters fmu_filename = 'CoupledClutches.fmu' start_time = 0.0 threshold = 2.0 stop_time = 2.0 step_size = 1e-3 # download the FMU download_test_file('2.0', 'CoSimulation', 'MapleSim', '2016.2', 'CoupledClutches', fmu_filename) # read the model description model_description = read_model_description(fmu_filename) # 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 vr_inputs = vrs['inputs'] # normalized force on the 3rd clutch vr_outputs4 = vrs['outputs[4]'] # angular velocity of the 4th inertia # extract the FMU unzipdir = extract(fmu_filename) fmu = FMU2Slave(guid=model_description.guid, unzipDirectory=unzipdir, modelIdentifier=model_description.coSimulation.modelIdentifier, instanceName='instance1') # initialize fmu.instantiate() fmu.setupExperiment(startTime=start_time) fmu.enterInitializationMode() fmu.exitInitializationMode() time = start_time rows = [] # list to record the results # simulation loop while time < stop_time: # NOTE: the FMU.get*() and FMU.set*() functions take lists of # value references as arguments and return lists of values # set the input fmu.setReal([vr_inputs], [0.0 if time < 0.9 else 1.0]) # perform one step fmu.doStep(currentCommunicationPoint=time, communicationStepSize=step_size) # get the values for 'inputs' and 'outputs[4]' inputs, outputs4 = fmu.getReal([vr_inputs, vr_outputs4]) # use the threshold to terminate the simulation if outputs4 > threshold: print("Threshold reached at t = %g s" % time) break # append the results rows.append((time, inputs, outputs4)) # advance the time time += step_size fmu.terminate() fmu.freeInstance() # clean up shutil.rmtree(unzipdir) # convert the results to a structured NumPy array result = np.array(rows, dtype=np.dtype([('time', np.float64), ('inputs', np.float64), ('outputs[4]', np.float64)])) # plot the results if show_plot: plot_result(result) return time
def setUpClass(cls): # download the FMU download_test_file('2.0', 'ModelExchange', 'MapleSim', '2017', 'CoupledClutches', 'CoupledClutches.fmu')
def setUpClass(cls): download_test_file('2.0', 'CoSimulation', 'Dymola', '2017', 'Rectifier', 'Rectifier.fmu')