def setUp(self): """ Load the test model. """ self._bounce = load_fmu('bouncingBall.fmu',path_to_fmus_me1) self._dq = load_fmu('dq.fmu',path_to_fmus_me1) self._bounce.initialize() self._dq.initialize() self._bounceSim = FMIODE(self._bounce) self._dqSim = FMIODE(self._dq)
class Test_FMI_ODE: """ This class tests pyfmi.simulation.assimulo.FMIODE and together with Assimulo. Requires that Assimulo is installed. """ @classmethod def setUpClass(cls): """ Compile the test model. """ file_name = os.path.join(get_files_path(), 'Modelica', 'noState.mo') _ex1_name = compile_fmu("NoState.Example1", file_name) _ex2_name = compile_fmu("NoState.Example2", file_name) _cc_name = compile_fmu( "Modelica.Mechanics.Rotational.Examples.CoupledClutches") def setUp(self): """ Load the test model. """ self._bounce = load_fmu('bouncingBall.fmu', path_to_fmus_me1) self._dq = load_fmu('dq.fmu', path_to_fmus_me1) self._bounce.initialize() self._dq.initialize() self._bounceSim = FMIODE(self._bounce) self._dqSim = FMIODE(self._dq) @testattr(stddist=True) def test_cc_with_cvode(self): model = load_fmu( "Modelica_Mechanics_Rotational_Examples_CoupledClutches.fmu") opts = model.simulate_options() opts["solver"] = "CVode" opts["CVode_options"]["rtol"] = 1e-7 res = model.simulate(final_time=1.5, options=opts) assert (N.abs(res.final("J1.w") - 3.2450903041811698)) < 1e-4 @testattr(stddist=True) def test_cc_with_radau(self): model = load_fmu( "Modelica_Mechanics_Rotational_Examples_CoupledClutches.fmu") opts = model.simulate_options() opts["solver"] = "Radau5ODE" res = model.simulate(final_time=1.5, options=opts) assert (N.abs(res.final("J1.w") - 3.2450903041811698)) < 1e-3 @testattr(stddist=True) def test_cc_with_dopri(self): model = load_fmu( "Modelica_Mechanics_Rotational_Examples_CoupledClutches.fmu") opts = model.simulate_options() opts["solver"] = "Dopri5" res = model.simulate(final_time=1.5, options=opts) assert (N.abs(res.final("J1.w") - 3.2450903041811698)) < 1e-3 @testattr(stddist=True) def test_cc_with_lsodar(self): model = load_fmu( "Modelica_Mechanics_Rotational_Examples_CoupledClutches.fmu") opts = model.simulate_options() opts["solver"] = "LSODAR" opts["LSODAR_options"]["rtol"] = 1e-6 res = model.simulate(final_time=1.5, options=opts) assert (N.abs(res.final("J1.w") - 3.2450903041811698)) < 1e-3 @testattr(stddist=True) def test_cc_with_rodas(self): model = load_fmu( "Modelica_Mechanics_Rotational_Examples_CoupledClutches.fmu") opts = model.simulate_options() opts["solver"] = "RodasODE" opts["RodasODE_options"]["rtol"] = 1e-6 res = model.simulate(final_time=1.5, options=opts) assert (N.abs(res.final("J1.w") - 3.2450903041811698)) < 1e-3 @testattr(stddist=True) def test_no_state1(self): """ Tests simulation when there is no state in the model (Example1). """ model = load_fmu("NoState_Example1.fmu") res = model.simulate(final_time=10) nose.tools.assert_almost_equal(res.initial('x'), 1.000000000) nose.tools.assert_almost_equal(res.final('x'), -2.000000000) nose.tools.assert_almost_equal(res.initial('y'), -1.000000000) nose.tools.assert_almost_equal(res.final('y'), -1.000000000) nose.tools.assert_almost_equal(res.initial('z'), 1.000000000) nose.tools.assert_almost_equal(res.final('z'), 4.000000000) @testattr(stddist=True) def test_no_state2(self): """ Tests simulation when there is no state in the model (Example2). """ model = load_fmu("NoState_Example2.fmu") res = model.simulate(final_time=10) nose.tools.assert_almost_equal(res.initial('x'), -1.000000000) nose.tools.assert_almost_equal(res.final('x'), -1.000000000) @testattr(stddist=True) def test_result_name_file(self): """ Tests user naming of result file (FMIODE). """ res = self._dq.simulate(options={"initialize": False}) #Default name assert res.result_file == "dq_result.txt" assert os.path.exists(res.result_file) res = self._bounce.simulate( options={ "result_file_name": "bouncingBallt_result_test.txt", "initialize": False }) #User defined name assert res.result_file == "bouncingBallt_result_test.txt" assert os.path.exists(res.result_file) @testattr(stddist=True) def test_init(self): """ This tests the functionality of the method init. """ assert self._bounceSim._f_nbr == 2 assert self._bounceSim._g_nbr == 1 assert self._bounceSim.state_events == self._bounceSim.g assert self._bounceSim.y0[0] == 1.0 assert self._bounceSim.y0[1] == 0.0 assert self._dqSim._f_nbr == 1 assert self._dqSim._g_nbr == 0 try: self._dqSim.state_events raise FMUException('') except AttributeError: pass #sol = self._bounceSim._sol_real #nose.tools.assert_almost_equal(sol[0][0],1.000000000) #nose.tools.assert_almost_equal(sol[0][1],0.000000000) #nose.tools.assert_almost_equal(sol[0][2],0.000000000) #nose.tools.assert_almost_equal(sol[0][3],-9.81000000) @testattr(stddist=True) def test_f(self): """ This tests the functionality of the rhs. """ t = 1.0 y = N.array([1.0, 1.0]) rhs = self._bounceSim.rhs(t, y) nose.tools.assert_almost_equal(rhs[0], 1.00000000) nose.tools.assert_almost_equal(rhs[1], -9.8100000) @testattr(stddist=True) def test_g(self): """ This tests the functionality of the event indicators. """ t = 1.0 y = N.array([1.0, 1.0]) event = self._bounceSim.g(t, y, None) nose.tools.assert_almost_equal(event[0], 1.00000000) y = N.array([0.5, 1.0]) event = self._bounceSim.g(t, y, None) nose.tools.assert_almost_equal(event[0], 0.50000000) @testattr(stddist=True) def test_t(self): """ This tests the functionality of the time events. """ t = 1.0 y = N.array([1.0, 1.0]) time = self._bounceSim.t(t, y, None) assert time == None #Further testing of the time event function is needed. @testattr(stddist=True) def test_handle_event(self): """ This tests the functionality of the method handle_event. """ y = N.array([1., 1.]) self._bounceSim._model.continuous_states = y solver = lambda x: 1 solver.rtol = 1.e-4 solver.t = 1.0 solver.y = y solver.y_sol = [y] solver.report_continuously = False self._bounceSim.initialize(solver) self._bounceSim.handle_event(solver, None) nose.tools.assert_almost_equal(solver.y[0], 1.00000000) nose.tools.assert_almost_equal(solver.y[1], -0.70000000) #Further testing of the handle_event function is needed. @testattr(stddist=True) def test_completed_step(self): """ This tests the functionality of the method completed_step. """ y = N.array([1., 1.]) solver = lambda x: 1 solver.t = 1.0 solver.y = y assert self._bounceSim.step_events(solver) == 0 #Further testing of the completed step function is needed. @testattr(windows=True) def test_simulation_completed_step_cvode(self): """ This tests a simulation of a Pendulum with dynamic state selection. """ model = load_fmu('Pendulum_0Dynamic.fmu', path_to_fmus_me1) res = model.simulate(final_time=10) nose.tools.assert_almost_equal(res.initial('x'), 1.000000, 4) nose.tools.assert_almost_equal(res.initial('y'), 0.000000, 4) nose.tools.assert_almost_equal(res.final('x'), 0.290109468, 4) nose.tools.assert_almost_equal(res.final('y'), -0.956993467, 4) model = FMUModel('Pendulum_0Dynamic.fmu', path_to_fmus_me1) res = model.simulate(final_time=10, options={'ncp': 1000}) nose.tools.assert_almost_equal(res.initial('x'), 1.000000, 4) nose.tools.assert_almost_equal(res.initial('y'), 0.000000, 4) @testattr(windows=True) def test_simulation_completed_step_radau(self): model = load_fmu('Pendulum_0Dynamic.fmu', path_to_fmus_me1) opts = model.simulate_options() opts["solver"] = "Radau5ODE" res = model.simulate(final_time=10, options=opts) assert N.abs(res.final('y') + 0.956993467) < 1e-2 assert N.abs(res.final('x') - 0.290109468) < 1e-1 model = FMUModel('Pendulum_0Dynamic.fmu', path_to_fmus_me1) opts["ncp"] = 1000 res = model.simulate(final_time=10, options=opts) assert N.abs(res.final('y') + 0.956993467) < 1e-2 assert N.abs(res.final('x') - 0.290109468) < 1e-1 @testattr(windows=True) def test_simulation_completed_step_dopri(self): model = load_fmu('Pendulum_0Dynamic.fmu', path_to_fmus_me1) opts = model.simulate_options() opts["solver"] = "Dopri5" res = model.simulate(final_time=10, options=opts) assert N.abs(res.final('y') + 0.956993467) < 1e-1 assert N.abs(res.final('x') - 0.290109468) < 1e-1 model = FMUModel('Pendulum_0Dynamic.fmu', path_to_fmus_me1) opts["ncp"] = 1000 res = model.simulate(final_time=10, options=opts) assert N.abs(res.final('y') + 0.956993467) < 1e-1 assert N.abs(res.final('x') - 0.290109468) < 1e-1 @testattr(windows=True) def test_simulation_completed_step_rodas(self): model = load_fmu('Pendulum_0Dynamic.fmu', path_to_fmus_me1) opts = model.simulate_options() opts["solver"] = "RodasODE" res = model.simulate(final_time=10, options=opts) assert N.abs(res.final('y') + 0.956993467) < 1e-1 assert N.abs(res.final('x') - 0.290109468) < 1e-1 model = FMUModel('Pendulum_0Dynamic.fmu', path_to_fmus_me1) opts["ncp"] = 1000 res = model.simulate(final_time=10, options=opts) assert N.abs(res.final('y') + 0.956993467) < 1e-1 assert N.abs(res.final('x') - 0.290109468) < 1e-1 @testattr(windows=True) def test_simulation_completed_step_lsodar(self): model = load_fmu('Pendulum_0Dynamic.fmu', path_to_fmus_me1) opts = model.simulate_options() opts["solver"] = "LSODAR" res = model.simulate(final_time=10, options=opts) assert N.abs(res.final('y') + 0.956993467) < 1e-1 assert N.abs(res.final('x') - 0.290109468) < 1e-1 model = FMUModel('Pendulum_0Dynamic.fmu', path_to_fmus_me1) opts["ncp"] = 1000 res = model.simulate(final_time=10, options=opts) assert N.abs(res.final('y') + 0.956993467) < 1e-1 assert N.abs(res.final('x') - 0.290109468) < 1e-1 @testattr(windows=True) def test_terminate_simulation(self): """ This tests a simulation with an event of terminate simulation. """ model = load_fmu('Robot.fmu', path_to_fmus_me1) res = model.simulate(final_time=2.0) solver = res.solver nose.tools.assert_almost_equal(solver.t, 1.856045, places=3) @testattr(windows=True) def test_typeDefinitions_simulation(self): """ This tests a FMU with typeDefinitions including StringType and BooleanType """ model = load_fmu('Robot_Dym74FD01.fmu', path_to_fmus_me1) res = model.simulate(final_time=2.0) solver = res.solver nose.tools.assert_almost_equal(solver.t, 1.856045, places=3) @testattr(stddist=True) def test_assert_raises_sensitivity_parameters(self): """ This tests that an exception is raised if a sensitivity calculation is to be perfomed and the parameters are not contained in the model. """ fmu_name = compile_fmu('EventIter.EventMiddleIter', os.path.join(path_to_mos, 'EventIter.mo')) model = load_fmu(fmu_name) opts = model.simulate_options() opts["sensitivities"] = ["hej", "hopp"] nose.tools.assert_raises(FMUException, model.simulate, 0, 1, (), 'AssimuloFMIAlg', opts) @testattr(windows=True) def test_assert_raises_sensitivity_without_jmodelica(self): model = load_fmu( "Modelica_Mechanics_Rotational_Examples_CoupledClutches_ME.fmu", path_to_fmus_me1) opts = model.simulate_options() opts["sensitivities"] = ["J1.w"] nose.tools.assert_raises(Exception, model.simulate, 0, 1, (), 'AssimuloFMIAlg', opts) @testattr(stddist=True) def test_event_iteration(self): """ This tests FMUs with event iteration (JModelica.org). """ fmu_name = compile_fmu('EventIter.EventMiddleIter', os.path.join(path_to_mos, 'EventIter.mo')) model = load_fmu(fmu_name) sim_res = model.simulate(final_time=10) nose.tools.assert_almost_equal(sim_res.initial('x'), 2.00000, 4) nose.tools.assert_almost_equal(sim_res.final('x'), 10.000000, 4) nose.tools.assert_almost_equal(sim_res.final('y'), 3.0000000, 4) nose.tools.assert_almost_equal(sim_res.final('z'), 2.0000000, 4) fmu_name = compile_fmu('EventIter.EventStartIter', os.path.join(path_to_mos, 'EventIter.mo')) model = FMUModel(fmu_name) sim_res = model.simulate(final_time=10) nose.tools.assert_almost_equal(sim_res.initial('x'), 1.00000, 4) nose.tools.assert_almost_equal(sim_res.initial('y'), -1.00000, 4) nose.tools.assert_almost_equal(sim_res.initial('z'), 1.00000, 4) nose.tools.assert_almost_equal(sim_res.final('x'), -2.000000, 4) nose.tools.assert_almost_equal(sim_res.final('y'), -1.0000000, 4) nose.tools.assert_almost_equal(sim_res.final('z'), 4.0000000, 4) @testattr(stddist=True) def test_changed_starttime(self): """ This tests a simulation with different start time. """ bounce = FMUModel('bouncingBall.fmu', path_to_fmus_me1) #bounce.initialize() opts = bounce.simulate_options() opts["CVode_options"]["rtol"] = 1e-4 opts["CVode_options"]["atol"] = 1e-6 res = bounce.simulate(start_time=2., final_time=5., options=opts) nose.tools.assert_almost_equal(res.initial('h'), 1.000000, 5) nose.tools.assert_almost_equal(res.final('h'), -0.98048862, 4) nose.tools.assert_almost_equal(res.final('time'), 5.000000, 5) @testattr(stddist=True) def test_basic_simulation(self): """ This tests the basic simulation and writing. """ #Writing continuous bounce = load_fmu('bouncingBall.fmu', path_to_fmus_me1) #bounce.initialize() opts = bounce.simulate_options() opts["CVode_options"]["rtol"] = 1e-4 opts["CVode_options"]["atol"] = 1e-6 res = bounce.simulate(final_time=3., options=opts) nose.tools.assert_almost_equal(res.initial('h'), 1.000000, 5) nose.tools.assert_almost_equal(res.final('h'), -0.9804523, 5) nose.tools.assert_almost_equal(res.final('time'), 3.000000, 5) #Writing after bounce = load_fmu('bouncingBall.fmu', path_to_fmus_me1) bounce.initialize() opt = bounce.simulate_options() opt['initialize'] = False opt["CVode_options"]["rtol"] = 1e-4 opt["CVode_options"]["atol"] = 1e-6 res = bounce.simulate(final_time=3., options=opt) nose.tools.assert_almost_equal(res.initial('h'), 1.000000, 5) nose.tools.assert_almost_equal(res.final('h'), -0.9804523, 5) nose.tools.assert_almost_equal(res.final('time'), 3.000000, 5) #Test with predefined FMUModel model = load_fmu(os.path.join(path_to_fmus_me1, 'bouncingBall.fmu')) #model.initialize() res = model.simulate(final_time=3., options=opts) nose.tools.assert_almost_equal(res.initial('h'), 1.000000, 5) nose.tools.assert_almost_equal(res.final('h'), -0.9804523, 5) nose.tools.assert_almost_equal(res.final('time'), 3.000000, 5) @testattr(stddist=True) def test_default_simulation(self): """ This test the default values of the simulation using simulate. """ #Writing continuous bounce = load_fmu('bouncingBall.fmu', path_to_fmus_me1) opts = bounce.simulate_options() opts["CVode_options"]["rtol"] = 1e-4 opts["CVode_options"]["atol"] = 1e-6 res = bounce.simulate(final_time=3., options=opts) nose.tools.assert_almost_equal(res.solver.rtol, 1e-4, 6) assert res.solver.iter == 'Newton' nose.tools.assert_almost_equal(res.initial('h'), 1.000000, 5) nose.tools.assert_almost_equal(res.final('h'), -0.9804523, 5) nose.tools.assert_almost_equal(res.final('time'), 3.000000, 5) #Writing continuous bounce = load_fmu('bouncingBall.fmu', path_to_fmus_me1) #bounce.initialize(options={'initialize':False}) res = bounce.simulate(final_time=3., options={ 'initialize': True, 'CVode_options': { 'iter': 'FixedPoint', 'rtol': 1e-6, 'atol': 1e-6 } }) nose.tools.assert_almost_equal(res.solver.rtol, 0.00000100, 7) assert res.solver.iter == 'FixedPoint' nose.tools.assert_almost_equal(res.initial('h'), 1.000000, 5) nose.tools.assert_almost_equal(res.final('h'), -0.98018113, 5) nose.tools.assert_almost_equal(res.final('time'), 3.000000, 5) @testattr(stddist=True) def test_reset(self): """ Test resetting an FMU. (Multiple instances is NOT supported on Dymola FMUs) """ #Writing continuous bounce = load_fmu('bouncingBall.fmu', path_to_fmus_me1) opts = bounce.simulate_options() opts["CVode_options"]["rtol"] = 1e-4 opts["CVode_options"]["atol"] = 1e-6 #bounce.initialize() res = bounce.simulate(final_time=3., options=opts) nose.tools.assert_almost_equal(res.initial('h'), 1.000000, 5) nose.tools.assert_almost_equal(res.final('h'), -0.9804523, 5) bounce.reset() #bounce.initialize() nose.tools.assert_almost_equal(bounce.get('h'), 1.00000, 5) res = bounce.simulate(final_time=3., options=opts) nose.tools.assert_almost_equal(res.initial('h'), 1.000000, 5) nose.tools.assert_almost_equal(res.final('h'), -0.9804523, 5)
def __init__(self, start_time, final_time, input, model, options): """ Create a simulation algorithm using Assimulo. Parameters:: model -- fmi.FMUModel object representation of the model. options -- The options that should be used in the algorithm. For details on the options, see: * model.simulate_options('AssimuloFMIAlgOptions') or look at the docstring with help: * help(pyfmi.fmi_algorithm_drivers.AssimuloFMIAlgOptions) Valid values are: - A dict that overrides some or all of the default values provided by AssimuloFMIAlgOptions. An empty dict will thus give all options with default values. - AssimuloFMIAlgOptions object. """ self.model = model self.timings = {} self.time_start_total = timer() try: import assimulo except: raise fmi.FMUException( 'Could not find Assimulo package. Check pyfmi.check_packages()') # import Assimulo dependent classes from pyfmi.simulation.assimulo_interface import FMIODE, FMIODESENS, FMIODE2, FMIODESENS2 # set start time, final time and input trajectory self.start_time = start_time self.final_time = final_time self.input = input # handle options argument if isinstance(options, dict) and not \ isinstance(options, AssimuloFMIAlgOptions): # user has passed dict with options or empty dict = default self.options = AssimuloFMIAlgOptions(options) elif isinstance(options, AssimuloFMIAlgOptions): # user has passed AssimuloFMIAlgOptions instance self.options = options else: raise InvalidAlgorithmOptionException(options) # set options self._set_options() #time_start = timer() input_traj = None if self.input: if hasattr(self.input[1],"__call__"): input_traj=(self.input[0], TrajectoryUserFunction(self.input[1])) else: input_traj=(self.input[0], TrajectoryLinearInterpolation(self.input[1][:,0], self.input[1][:,1:])) #Sets the inputs, if any input_names = [input_traj[0]] if isinstance(input_traj[0],str) else input_traj[0] input_values = input_traj[1].eval(self.start_time)[0,:] if len(input_names) != len(input_values): raise fmi.FMUException("The number of input variables is not equal to the number of input values, please verify the input object.") self.model.set(input_names, input_values) if self.options["result_handling"] == "file": self.result_handler = ResultHandlerFile(self.model) elif self.options["result_handling"] == "binary": if self.options["sensitivities"]: logging.warning('The binary result file do not currently support storing of sensitivity results. Switching to textual result format.') self.result_handler = ResultHandlerFile(self.model) else: self.result_handler = ResultHandlerBinaryFile(self.model) elif self.options["result_handling"] == "memory": self.result_handler = ResultHandlerMemory(self.model) elif self.options["result_handling"] == "csv": self.result_handler = ResultHandlerCSV(self.model, delimiter=",") elif self.options["result_handling"] == "custom": self.result_handler = self.options["result_handler"] if self.result_handler is None: raise fmi.FMUException("The result handler needs to be specified when using a custom result handling.") if not isinstance(self.result_handler, ResultHandler): raise fmi.FMUException("The result handler needs to be a subclass of ResultHandler.") elif self.options["result_handling"] == "none": #No result handling (for performance) self.result_handler = ResultHandlerDummy(self.model) else: raise fmi.FMUException("Unknown option to result_handling.") self.result_handler.set_options(self.options) time_end = timer() #self.timings["creating_result_object"] = time_end - time_start time_start = time_end time_res_init = 0.0 # Initialize? if self.options['initialize']: try: rtol = self.solver_options['rtol'] except KeyError: rtol, atol = self.model.get_tolerances() if isinstance(self.model, fmi.FMUModelME1): self.model.time = start_time #Set start time before initialization self.model.initialize(tolerance=rtol) elif isinstance(self.model, fmi.FMUModelME2) or isinstance(self.model, fmi_coupled.CoupledFMUModelME2): self.model.setup_experiment(tolerance=rtol, start_time=self.start_time, stop_time=self.final_time) self.model.initialize() self.model.event_update() self.model.enter_continuous_time_mode() else: raise fmi.FMUException("Unknown model.") time_res_init = timer() self.result_handler.initialize_complete() time_res_init = timer() - time_res_init elif self.model.time is None and isinstance(self.model, fmi.FMUModelME2): raise fmi.FMUException("Setup Experiment has not been called, this has to be called prior to the initialization call.") elif self.model.time is None: raise fmi.FMUException("The model need to be initialized prior to calling the simulate method if the option 'initialize' is set to False") #See if there is an time event at start time if isinstance(self.model, fmi.FMUModelME1): event_info = self.model.get_event_info() if event_info.upcomingTimeEvent and event_info.nextEventTime == model.time: self.model.event_update() if abs(start_time - model.time) > 1e-14: logging.warning('The simulation start time (%f) and the current time in the model (%f) is different. Is the simulation start time correctly set?'%(start_time, model.time)) time_end = timer() self.timings["initializing_fmu"] = time_end - time_start - time_res_init time_start = time_end self.result_handler.simulation_start() self.timings["initializing_result"] = timer() - time_start + time_res_init # Sensitivities? if self.options["sensitivities"]: if self.model.get_generation_tool() != "JModelica.org" and \ self.model.get_generation_tool() != "Optimica Compiler Toolkit": if isinstance(self.model, fmi.FMUModelME2): for var in self.options["sensitivities"]: causality = self.model.get_variable_causality(var) if causality != fmi.FMI2_INPUT: raise fmi.FMUException("The sensitivity parameter is not specified as an input which is required.") else: raise fmi.FMUException("Sensitivity calculations only possible with JModelica.org generated FMUs") if self.options["solver"] != "CVode": raise fmi.FMUException("Sensitivity simulations currently only supported using the solver CVode.") #Checks to see if all the sensitivities are inside the model #else there will be an exception self.model.get(self.options["sensitivities"]) if not self.input and (isinstance(self.model, fmi.FMUModelME2) or isinstance(self.model, fmi_coupled.CoupledFMUModelME2)): if self.options["sensitivities"]: self.probl = FMIODESENS2(self.model, result_file_name=self.result_file_name, with_jacobian=self.with_jacobian, start_time=self.start_time, parameters=self.options["sensitivities"],logging=self.options["logging"], result_handler=self.result_handler) else: self.probl = FMIODE2(self.model, result_file_name=self.result_file_name, with_jacobian=self.with_jacobian, start_time=self.start_time,logging=self.options["logging"], result_handler=self.result_handler,extra_equations=self.options["extra_equations"]) elif isinstance(self.model, fmi.FMUModelME2) or isinstance(self.model, fmi_coupled.CoupledFMUModelME2): if self.options["sensitivities"]: self.probl = FMIODESENS2( self.model, input_traj, result_file_name=self.result_file_name, with_jacobian=self.with_jacobian, start_time=self.start_time,parameters=self.options["sensitivities"],logging=self.options["logging"], result_handler=self.result_handler) else: self.probl = FMIODE2( self.model, input_traj, result_file_name=self.result_file_name, with_jacobian=self.with_jacobian, start_time=self.start_time,logging=self.options["logging"], result_handler=self.result_handler, extra_equations=self.options["extra_equations"]) elif not self.input: if self.options["sensitivities"]: self.probl = FMIODESENS(self.model, result_file_name=self.result_file_name,with_jacobian=self.with_jacobian,start_time=self.start_time,parameters=self.options["sensitivities"],logging=self.options["logging"], result_handler=self.result_handler) else: self.probl = FMIODE(self.model, result_file_name=self.result_file_name,with_jacobian=self.with_jacobian,start_time=self.start_time,logging=self.options["logging"], result_handler=self.result_handler) else: if self.options["sensitivities"]: self.probl = FMIODESENS( self.model, input_traj, result_file_name=self.result_file_name,with_jacobian=self.with_jacobian,start_time=self.start_time,parameters=self.options["sensitivities"],logging=self.options["logging"], result_handler=self.result_handler) else: self.probl = FMIODE( self.model, input_traj, result_file_name=self.result_file_name,with_jacobian=self.with_jacobian,start_time=self.start_time,logging=self.options["logging"], result_handler=self.result_handler) # instantiate solver and set options self.simulator = self.solver(self.probl) self._set_solver_options()
class Test_FMI_ODE: """ This class tests pyfmi.simulation.assimulo.FMIODE and together with Assimulo. Requires that Assimulo is installed. """ @classmethod def setUpClass(cls): """ Compile the test model. """ file_name = os.path.join(get_files_path(), 'Modelica', 'noState.mo') _ex1_name = compile_fmu("NoState.Example1", file_name) _ex2_name = compile_fmu("NoState.Example2", file_name) _cc_name = compile_fmu("Modelica.Mechanics.Rotational.Examples.CoupledClutches") def setUp(self): """ Load the test model. """ self._bounce = load_fmu('bouncingBall.fmu',path_to_fmus_me1) self._dq = load_fmu('dq.fmu',path_to_fmus_me1) self._bounce.initialize() self._dq.initialize() self._bounceSim = FMIODE(self._bounce) self._dqSim = FMIODE(self._dq) @testattr(stddist = True) def test_cc_with_cvode(self): model = load_fmu("Modelica_Mechanics_Rotational_Examples_CoupledClutches.fmu") opts = model.simulate_options() opts["solver"] = "CVode" opts["CVode_options"]["rtol"] = 1e-7 res = model.simulate(final_time=1.5,options=opts) assert (N.abs(res.final("J1.w") - 3.2450903041811698)) < 1e-4 @testattr(stddist = True) def test_no_result(self): opts = self._bounce.simulate_options() opts["result_handling"] = "none" opts["initialize"] = False res = self._bounce.simulate(options=opts) nose.tools.assert_raises(Exception,res._get_result_data) @testattr(stddist = True) def test_cc_with_radau(self): model = load_fmu("Modelica_Mechanics_Rotational_Examples_CoupledClutches.fmu") opts = model.simulate_options() opts["solver"] = "Radau5ODE" res = model.simulate(final_time=1.5,options=opts) assert (N.abs(res.final("J1.w") - 3.2450903041811698)) < 1e-3 @testattr(stddist = True) def test_cc_with_dopri(self): model = load_fmu("Modelica_Mechanics_Rotational_Examples_CoupledClutches.fmu") opts = model.simulate_options() opts["solver"] = "Dopri5" res = model.simulate(final_time=1.5,options=opts) assert (N.abs(res.final("J1.w") - 3.2450903041811698)) < 1e-3 @testattr(stddist = True) def test_cc_with_lsodar(self): model = load_fmu("Modelica_Mechanics_Rotational_Examples_CoupledClutches.fmu") opts = model.simulate_options() opts["solver"] = "LSODAR" opts["LSODAR_options"]["rtol"] = 1e-6 res = model.simulate(final_time=1.5,options=opts) assert (N.abs(res.final("J1.w") - 3.2450903041811698)) < 1e-3 @testattr(stddist = True) def test_cc_with_rodas(self): model = load_fmu("Modelica_Mechanics_Rotational_Examples_CoupledClutches.fmu") opts = model.simulate_options() opts["solver"] = "RodasODE" opts["RodasODE_options"]["rtol"] = 1e-6 res = model.simulate(final_time=1.5,options=opts) assert (N.abs(res.final("J1.w") - 3.2450903041811698)) < 1e-3 @testattr(stddist = True) def test_no_state1(self): """ Tests simulation when there is no state in the model (Example1). """ model = load_fmu("NoState_Example1.fmu") res = model.simulate(final_time=10) nose.tools.assert_almost_equal(res.initial('x') ,1.000000000) nose.tools.assert_almost_equal(res.final('x'),-2.000000000) nose.tools.assert_almost_equal(res.initial('y') ,-1.000000000) nose.tools.assert_almost_equal(res.final('y'),-1.000000000) nose.tools.assert_almost_equal(res.initial('z') ,1.000000000) nose.tools.assert_almost_equal(res.final('z'),4.000000000) @testattr(stddist = True) def test_no_state2(self): """ Tests simulation when there is no state in the model (Example2). """ model = load_fmu("NoState_Example2.fmu") res = model.simulate(final_time=10) nose.tools.assert_almost_equal(res.initial('x') ,-1.000000000) nose.tools.assert_almost_equal(res.final('x'),-1.000000000) @testattr(stddist = True) def test_result_name_file(self): """ Tests user naming of result file (FMIODE). """ res = self._dq.simulate(options={"initialize":False}) #Default name assert res.result_file == "dq_result.txt" assert os.path.exists(res.result_file) res = self._bounce.simulate(options={"result_file_name": "bouncingBallt_result_test.txt", "initialize":False}) #User defined name assert res.result_file == "bouncingBallt_result_test.txt" assert os.path.exists(res.result_file) @testattr(stddist = True) def test_init(self): """ This tests the functionality of the method init. """ assert self._bounceSim._f_nbr == 2 assert self._bounceSim._g_nbr == 1 assert self._bounceSim.state_events == self._bounceSim.g assert self._bounceSim.y0[0] == 1.0 assert self._bounceSim.y0[1] == 0.0 assert self._dqSim._f_nbr == 1 assert self._dqSim._g_nbr == 0 try: self._dqSim.state_events raise FMUException('') except AttributeError: pass #sol = self._bounceSim._sol_real #nose.tools.assert_almost_equal(sol[0][0],1.000000000) #nose.tools.assert_almost_equal(sol[0][1],0.000000000) #nose.tools.assert_almost_equal(sol[0][2],0.000000000) #nose.tools.assert_almost_equal(sol[0][3],-9.81000000) @testattr(stddist = True) def test_f(self): """ This tests the functionality of the rhs. """ t = 1.0 y = N.array([1.0,1.0]) rhs = self._bounceSim.rhs(t,y) nose.tools.assert_almost_equal(rhs[0],1.00000000) nose.tools.assert_almost_equal(rhs[1],-9.8100000) @testattr(stddist = True) def test_g(self): """ This tests the functionality of the event indicators. """ t = 1.0 y = N.array([1.0,1.0]) event = self._bounceSim.g(t,y,None) nose.tools.assert_almost_equal(event[0],1.00000000) y = N.array([0.5,1.0]) event = self._bounceSim.g(t,y,None) nose.tools.assert_almost_equal(event[0],0.50000000) @testattr(stddist = True) def test_t(self): """ This tests the functionality of the time events. """ t = 1.0 y = N.array([1.0,1.0]) time = self._bounceSim.t(t,y,None) assert time == None #Further testing of the time event function is needed. @testattr(stddist = True) def test_handle_event(self): """ This tests the functionality of the method handle_event. """ y = N.array([1.,1.]) self._bounceSim._model.continuous_states = y solver = lambda x:1 solver.rtol = 1.e-4 solver.t = 1.0 solver.y = y solver.y_sol = [y] solver.report_continuously = False self._bounceSim.initialize(solver) self._bounceSim.handle_event(solver, None) nose.tools.assert_almost_equal(solver.y[0],1.00000000) nose.tools.assert_almost_equal(solver.y[1],-0.70000000) #Further testing of the handle_event function is needed. @testattr(stddist = True) def test_completed_step(self): """ This tests the functionality of the method completed_step. """ y = N.array([1.,1.]) solver = lambda x:1 solver.t = 1.0 solver.y = y assert self._bounceSim.step_events(solver) == 0 #Further testing of the completed step function is needed. @testattr(windows = True) def test_simulation_completed_step_cvode(self): """ This tests a simulation of a Pendulum with dynamic state selection. """ model = load_fmu('Pendulum_0Dynamic.fmu', path_to_fmus_me1) res = model.simulate(final_time=10) nose.tools.assert_almost_equal(res.initial('x'), 1.000000, 4) nose.tools.assert_almost_equal(res.initial('y'), 0.000000, 4) nose.tools.assert_almost_equal(res.final('x'), 0.290109468, 4) nose.tools.assert_almost_equal(res.final('y'), -0.956993467, 4) model = FMUModel('Pendulum_0Dynamic.fmu', path_to_fmus_me1) res = model.simulate(final_time=10, options={'ncp':1000}) nose.tools.assert_almost_equal(res.initial('x'), 1.000000, 4) nose.tools.assert_almost_equal(res.initial('y'), 0.000000, 4) @testattr(windows = True) def test_simulation_completed_step_radau(self): model = load_fmu('Pendulum_0Dynamic.fmu', path_to_fmus_me1) opts = model.simulate_options() opts["solver"] = "Radau5ODE" res = model.simulate(final_time=10, options=opts) assert N.abs(res.final('y')+0.956993467) < 1e-2 assert N.abs(res.final('x')-0.290109468) < 1e-1 model = FMUModel('Pendulum_0Dynamic.fmu', path_to_fmus_me1) opts["ncp"] = 1000 res = model.simulate(final_time=10, options=opts) assert N.abs(res.final('y')+0.956993467) < 1e-2 assert N.abs(res.final('x')-0.290109468) < 1e-1 @testattr(windows = True) def test_simulation_completed_step_dopri(self): model = load_fmu('Pendulum_0Dynamic.fmu', path_to_fmus_me1) opts = model.simulate_options() opts["solver"] = "Dopri5" res = model.simulate(final_time=10, options=opts) assert N.abs(res.final('y')+0.956993467) < 1e-1 assert N.abs(res.final('x')-0.290109468) < 1e-1 model = FMUModel('Pendulum_0Dynamic.fmu', path_to_fmus_me1) opts["ncp"] = 1000 res = model.simulate(final_time=10, options=opts) assert N.abs(res.final('y')+0.956993467) < 1e-1 assert N.abs(res.final('x')-0.290109468) < 1e-1 @testattr(windows = True) def test_simulation_completed_step_rodas(self): model = load_fmu('Pendulum_0Dynamic.fmu', path_to_fmus_me1) opts = model.simulate_options() opts["solver"] = "RodasODE" res = model.simulate(final_time=10, options=opts) assert N.abs(res.final('y')+0.956993467) < 1e-1 assert N.abs(res.final('x')-0.290109468) < 1e-1 model = FMUModel('Pendulum_0Dynamic.fmu', path_to_fmus_me1) opts["ncp"] = 1000 res = model.simulate(final_time=10, options=opts) assert N.abs(res.final('y')+0.956993467) < 1e-1 assert N.abs(res.final('x')-0.290109468) < 1e-1 @testattr(windows = True) def test_simulation_completed_step_lsodar(self): model = load_fmu('Pendulum_0Dynamic.fmu', path_to_fmus_me1) opts = model.simulate_options() opts["solver"] = "LSODAR" res = model.simulate(final_time=10, options=opts) assert N.abs(res.final('y')+0.956993467) < 1e-1 assert N.abs(res.final('x')-0.290109468) < 1e-1 model = FMUModel('Pendulum_0Dynamic.fmu', path_to_fmus_me1) opts["ncp"] = 1000 res = model.simulate(final_time=10, options=opts) assert N.abs(res.final('y')+0.956993467) < 1e-1 assert N.abs(res.final('x')-0.290109468) < 1e-1 @testattr(windows = True) def test_terminate_simulation(self): """ This tests a simulation with an event of terminate simulation. """ model = load_fmu('Robot.fmu', path_to_fmus_me1) res = model.simulate(final_time=2.0) solver = res.solver nose.tools.assert_almost_equal(solver.t, 1.856045, places=3) @testattr(windows = True) def test_typeDefinitions_simulation(self): """ This tests a FMU with typeDefinitions including StringType and BooleanType """ model = load_fmu('Robot_Dym74FD01.fmu', path_to_fmus_me1) res = model.simulate(final_time=2.0) solver = res.solver nose.tools.assert_almost_equal(solver.t, 1.856045, places=3) @testattr(stddist = True) def test_assert_raises_sensitivity_parameters(self): """ This tests that an exception is raised if a sensitivity calculation is to be perfomed and the parameters are not contained in the model. """ fmu_name = compile_fmu('EventIter.EventMiddleIter', os.path.join(path_to_mos,'EventIter.mo')) model = load_fmu(fmu_name) opts = model.simulate_options() opts["sensitivities"] = ["hej", "hopp"] nose.tools.assert_raises(FMUException,model.simulate,0,1,(),'AssimuloFMIAlg',opts) @testattr(windows = True) def test_assert_raises_sensitivity_without_jmodelica(self): model = load_fmu("Modelica_Mechanics_Rotational_Examples_CoupledClutches_ME.fmu", path_to_fmus_me1) opts = model.simulate_options() opts["sensitivities"] = ["J1.w"] nose.tools.assert_raises(Exception,model.simulate,0,1,(),'AssimuloFMIAlg',opts) @testattr(stddist = True) def test_event_iteration(self): """ This tests FMUs with event iteration (JModelica.org). """ fmu_name = compile_fmu('EventIter.EventMiddleIter', os.path.join(path_to_mos,'EventIter.mo')) model = load_fmu(fmu_name) sim_res = model.simulate(final_time=10) nose.tools.assert_almost_equal(sim_res.initial('x'), 2.00000, 4) nose.tools.assert_almost_equal(sim_res.final('x'), 10.000000, 4) nose.tools.assert_almost_equal(sim_res.final('y'), 3.0000000, 4) nose.tools.assert_almost_equal(sim_res.final('z'), 2.0000000, 4) fmu_name = compile_fmu('EventIter.EventStartIter', os.path.join(path_to_mos,'EventIter.mo')) model = FMUModel(fmu_name) sim_res = model.simulate(final_time=10) nose.tools.assert_almost_equal(sim_res.initial('x'), 1.00000, 4) nose.tools.assert_almost_equal(sim_res.initial('y'), -1.00000, 4) nose.tools.assert_almost_equal(sim_res.initial('z'), 1.00000, 4) nose.tools.assert_almost_equal(sim_res.final('x'), -2.000000, 4) nose.tools.assert_almost_equal(sim_res.final('y'), -1.0000000, 4) nose.tools.assert_almost_equal(sim_res.final('z'), 4.0000000, 4) @testattr(stddist = True) def test_changed_starttime(self): """ This tests a simulation with different start time. """ bounce = FMUModel('bouncingBall.fmu', path_to_fmus_me1) #bounce.initialize() opts = bounce.simulate_options() opts["CVode_options"]["rtol"] = 1e-4 opts["CVode_options"]["atol"] = 1e-6 res = bounce.simulate(start_time=2.,final_time=5.,options=opts) nose.tools.assert_almost_equal(res.initial('h'),1.000000,5) nose.tools.assert_almost_equal(res.final('h'),-0.98048862,4) nose.tools.assert_almost_equal(res.final('time'),5.000000,5) @testattr(stddist = True) def test_basic_simulation(self): """ This tests the basic simulation and writing. """ #Writing continuous bounce = load_fmu('bouncingBall.fmu', path_to_fmus_me1) #bounce.initialize() opts = bounce.simulate_options() opts["CVode_options"]["rtol"] = 1e-4 opts["CVode_options"]["atol"] = 1e-6 res = bounce.simulate(final_time=3., options=opts) nose.tools.assert_almost_equal(res.initial('h'),1.000000,5) nose.tools.assert_almost_equal(res.final('h'),-0.9804523,5) nose.tools.assert_almost_equal(res.final('time'),3.000000,5) #Writing after bounce = load_fmu('bouncingBall.fmu', path_to_fmus_me1) bounce.initialize() opt = bounce.simulate_options() opt['initialize']=False opt["CVode_options"]["rtol"] = 1e-4 opt["CVode_options"]["atol"] = 1e-6 res = bounce.simulate(final_time=3., options=opt) nose.tools.assert_almost_equal(res.initial('h'),1.000000,5) nose.tools.assert_almost_equal(res.final('h'),-0.9804523,5) nose.tools.assert_almost_equal(res.final('time'),3.000000,5) #Test with predefined FMUModel model = load_fmu(os.path.join(path_to_fmus_me1,'bouncingBall.fmu')) #model.initialize() res = model.simulate(final_time=3.,options=opts) nose.tools.assert_almost_equal(res.initial('h'),1.000000,5) nose.tools.assert_almost_equal(res.final('h'),-0.9804523,5) nose.tools.assert_almost_equal(res.final('time'),3.000000,5) @testattr(stddist = True) def test_default_simulation(self): """ This test the default values of the simulation using simulate. """ #Writing continuous bounce = load_fmu('bouncingBall.fmu', path_to_fmus_me1) opts = bounce.simulate_options() opts["CVode_options"]["rtol"] = 1e-4 opts["CVode_options"]["atol"] = 1e-6 res = bounce.simulate(final_time=3., options=opts) nose.tools.assert_almost_equal(res.solver.rtol, 1e-4, 6) assert res.solver.iter == 'Newton' nose.tools.assert_almost_equal(res.initial('h'),1.000000,5) nose.tools.assert_almost_equal(res.final('h'),-0.9804523,5) nose.tools.assert_almost_equal(res.final('time'),3.000000,5) #Writing continuous bounce = load_fmu('bouncingBall.fmu', path_to_fmus_me1) #bounce.initialize(options={'initialize':False}) res = bounce.simulate(final_time=3., options={'initialize':True,'CVode_options':{'iter':'FixedPoint','rtol':1e-6,'atol':1e-6}}) nose.tools.assert_almost_equal(res.solver.rtol, 0.00000100, 7) assert res.solver.iter == 'FixedPoint' nose.tools.assert_almost_equal(res.initial('h'),1.000000,5) nose.tools.assert_almost_equal(res.final('h'),-0.98018113,5) nose.tools.assert_almost_equal(res.final('time'),3.000000,5) @testattr(stddist = True) def test_reset(self): """ Test resetting an FMU. (Multiple instances is NOT supported on Dymola FMUs) """ #Writing continuous bounce = load_fmu('bouncingBall.fmu', path_to_fmus_me1) opts = bounce.simulate_options() opts["CVode_options"]["rtol"] = 1e-4 opts["CVode_options"]["atol"] = 1e-6 #bounce.initialize() res = bounce.simulate(final_time=3., options=opts) nose.tools.assert_almost_equal(res.initial('h'),1.000000,5) nose.tools.assert_almost_equal(res.final('h'),-0.9804523,5) bounce.reset() #bounce.initialize() nose.tools.assert_almost_equal(bounce.get('h'), 1.00000,5) res = bounce.simulate(final_time=3.,options=opts) nose.tools.assert_almost_equal(res.initial('h'),1.000000,5) nose.tools.assert_almost_equal(res.final('h'),-0.9804523,5)
def __init__(self, start_time, final_time, input, model, options): """ Create a simulation algorithm using Assimulo. Parameters:: model -- fmi.FMUModel object representation of the model. options -- The options that should be used in the algorithm. For details on the options, see: * model.simulate_options('AssimuloFMIAlgOptions') or look at the docstring with help: * help(pyfmi.fmi_algorithm_drivers.AssimuloFMIAlgOptions) Valid values are: - A dict that overrides some or all of the default values provided by AssimuloFMIAlgOptions. An empty dict will thus give all options with default values. - AssimuloFMIAlgOptions object. """ self.model = model if not assimulo_present: raise Exception( 'Could not find Assimulo package. Check pyfmi.check_packages()' ) # set start time, final time and input trajectory self.start_time = start_time self.final_time = final_time self.input = input # handle options argument if isinstance(options, dict) and not \ isinstance(options, AssimuloFMIAlgOptions): # user has passed dict with options or empty dict = default self.options = AssimuloFMIAlgOptions(options) elif isinstance(options, AssimuloFMIAlgOptions): # user has passed AssimuloFMIAlgOptions instance self.options = options else: raise InvalidAlgorithmOptionException(options) # set options self._set_options() input_traj = None if self.input: if hasattr(self.input[1], "__call__"): input_traj = (self.input[0], TrajectoryUserFunction(self.input[1])) else: input_traj = (self.input[0], TrajectoryLinearInterpolation( self.input[1][:, 0], self.input[1][:, 1:])) #Sets the inputs, if any self.model.set(input_traj[0], input_traj[1].eval(self.start_time)[0, :]) if self.options["result_handling"] == "file": self.result_handler = ResultHandlerFile(self.model) elif self.options["result_handling"] == "memory": self.result_handler = ResultHandlerMemory(self.model) elif self.options["result_handling"] == "csv": self.result_handler = ResultHandlerCSV(self.model, delimiter=",") elif self.options["result_handling"] == "custom": self.result_handler = self.options["result_handler"] if self.result_handler == None: raise Exception( "The result handler needs to be specified when using a custom result handling." ) if not isinstance(self.result_handler, ResultHandler): raise Exception( "The result handler needs to be a subclass of ResultHandler." ) elif self.options[ "result_handling"] == "none": #No result handling (for performance) self.result_handler = ResultHandlerDummy(self.model) else: raise Exception("Unknown option to result_handling.") self.result_handler.set_options(self.options) # Initialize? if self.options['initialize']: try: rtol = self.solver_options['rtol'] except KeyError: rtol, atol = self.model.get_tolerances() if isinstance(self.model, fmi.FMUModelME1): self.model.time = start_time #Set start time before initialization self.model.initialize(relativeTolerance=rtol) elif isinstance(self.model, fmi.FMUModelME2): self.model.setup_experiment(tolerance=rtol, start_time=self.start_time, stop_time=self.final_time) self.model.initialize() self.model.event_update() self.model.enter_continuous_time_mode() else: raise Exception("Unknown model.") self.result_handler.initialize_complete() elif self.model.time == None and isinstance(self.model, fmi.FMUModelME2): raise Exception( "Setup Experiment has not been called, this has to be called prior to the initialization call." ) #See if there is an time event at start time if isinstance(self.model, fmi.FMUModelME1): event_info = self.model.get_event_info() if event_info.upcomingTimeEvent and event_info.nextEventTime == model.time: self.model.event_update() self.result_handler.simulation_start() # Sensitivities? if self.options["sensitivities"]: if self.model.get_generation_tool() != "JModelica.org": if isinstance(self.model, fmi.FMUModelME2): for var in self.options["sensitivities"]: causality = self.model.get_variable_causality(var) if causality != fmi.FMI2_INPUT: raise FMUException( "The sensitivity parameter is not specified as an input which is required." ) else: raise Exception( "Sensitivity calculations only possible with JModelica.org generated FMUs" ) if self.options["solver"] != "CVode": raise Exception( "Sensitivity simulations currently only supported using the solver CVode." ) #Checks to see if all the sensitivities are inside the model #else there will be an exception self.model.get(self.options["sensitivities"]) if not self.input and isinstance(self.model, fmi.FMUModelME2): if self.options["sensitivities"]: self.probl = FMIODESENS2( self.model, result_file_name=self.result_file_name, start_time=self.start_time, parameters=self.options["sensitivities"], logging=self.options["logging"], result_handler=self.result_handler) else: self.probl = FMIODE2( self.model, result_file_name=self.result_file_name, start_time=self.start_time, logging=self.options["logging"], result_handler=self.result_handler, extra_equations=self.options["extra_equations"]) elif isinstance(self.model, fmi.FMUModelME2): if self.options["sensitivities"]: self.probl = FMIODESENS2( self.model, input_traj, result_file_name=self.result_file_name, start_time=self.start_time, parameters=self.options["sensitivities"], logging=self.options["logging"], result_handler=self.result_handler) else: self.probl = FMIODE2( self.model, input_traj, result_file_name=self.result_file_name, start_time=self.start_time, logging=self.options["logging"], result_handler=self.result_handler, extra_equations=self.options["extra_equations"]) elif not self.input: if self.options["sensitivities"]: self.probl = FMIODESENS( self.model, result_file_name=self.result_file_name, with_jacobian=self.with_jacobian, start_time=self.start_time, parameters=self.options["sensitivities"], logging=self.options["logging"], result_handler=self.result_handler) else: self.probl = FMIODE(self.model, result_file_name=self.result_file_name, with_jacobian=self.with_jacobian, start_time=self.start_time, logging=self.options["logging"], result_handler=self.result_handler) else: if self.options["sensitivities"]: self.probl = FMIODESENS( self.model, input_traj, result_file_name=self.result_file_name, with_jacobian=self.with_jacobian, start_time=self.start_time, parameters=self.options["sensitivities"], logging=self.options["logging"], result_handler=self.result_handler) else: self.probl = FMIODE(self.model, input_traj, result_file_name=self.result_file_name, with_jacobian=self.with_jacobian, start_time=self.start_time, logging=self.options["logging"], result_handler=self.result_handler) # instantiate solver and set options self.simulator = self.solver(self.probl) self._set_solver_options()