def test_linear_example(self): model_sub_1 = Dummy_FMUModelME2([], "LinearStability.SubSystem1.fmu", me2_xml_path, _connect_dll=False) model_sub_2 = Dummy_FMUModelME2([], "LinearStability.SubSystem2.fmu", me2_xml_path, _connect_dll=False) def sub1(*args, **kwargs): u1 = model_sub_1.values[model_sub_1.get_variable_valueref("u1")] a1 = model_sub_1.values[model_sub_1.get_variable_valueref("a1")] b1 = model_sub_1.values[model_sub_1.get_variable_valueref("b1")] c1 = model_sub_1.values[model_sub_1.get_variable_valueref("c1")] d1 = model_sub_1.values[model_sub_1.get_variable_valueref("d1")] x1 = model_sub_1.continuous_states[0] model_sub_1.values[model_sub_1.get_variable_valueref("y1")] = c1*x1+d1*u1 model_sub_1.values[model_sub_1.get_variable_valueref("x1")] = x1 return np.array([a1*x1+b1*u1]) def sub2(*args, **kwargs): u2 = model_sub_2.values[model_sub_2.get_variable_valueref("u2")] a2 = model_sub_2.values[model_sub_2.get_variable_valueref("a2")] b2 = model_sub_2.values[model_sub_2.get_variable_valueref("b2")] c2 = model_sub_2.values[model_sub_2.get_variable_valueref("c2")] d2 = model_sub_2.values[model_sub_2.get_variable_valueref("d2")] x2 = model_sub_2.continuous_states[0] model_sub_2.values[model_sub_2.get_variable_valueref("y2")] = c2*x2+d2*u2 model_sub_2.values[model_sub_2.get_variable_valueref("x2")] = x2 return np.array([a2*x2+b2*u2]) model_sub_1.get_derivatives = sub1 model_sub_2.get_derivatives = sub2 models = [("First", model_sub_1), ("Second", model_sub_2)] connections = [(model_sub_1,"y1",model_sub_2,"u2"), (model_sub_2,"y2",model_sub_1,"u1")] coupled = CoupledFMUModelME2(models, connections=connections) opts = {"CVode_options": {"rtol":1e-6, "atol":1e-6}, "ncp":0} res = coupled.simulate(options=opts) nose.tools.assert_almost_equal(res.final("First.x1"),0.08597302307099872) nose.tools.assert_almost_equal(res.final("Second.x2"),0.0083923348082567) nose.tools.assert_almost_equal(res.initial("First.x1"),1.0) nose.tools.assert_almost_equal(res.initial("Second.x2"),1.0) nose.tools.assert_almost_equal(res.final("First.u1"),-0.25909975860402856) nose.tools.assert_almost_equal(res.final("Second.u2"),-0.0011806893910324295) nose.tools.assert_almost_equal(res.initial("First.u1"),-17.736842105263158) nose.tools.assert_almost_equal(res.initial("Second.u2"),-14.73684210526316)
def test_with_jacobian_option(self): model = Dummy_FMUModelME2([], "NoState.Example1.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = model.simulate_options() opts["solver"] = "CVode" opts["result_handling"] = "none" from pyfmi.fmi_algorithm_drivers import AssimuloFMIAlg, PYFMI_JACOBIAN_LIMIT class TempAlg(AssimuloFMIAlg): def solve(self): pass def run_case(expected, default="Default"): model.reset() res = model.simulate(final_time=1.5,options=opts, algorithm=TempAlg) assert res.options["with_jacobian"] == default, res.options["with_jacobian"] assert res.solver.problem._with_jacobian == expected, res.solver.problem._with_jacobian run_case(False) model.get_ode_sizes = lambda: (PYFMI_JACOBIAN_LIMIT+1, 0) run_case(True) opts["solver"] = "Radau5ODE" run_case(False) opts["solver"] = "CVode" opts["with_jacobian"] = False run_case(False, False) model.get_ode_sizes = lambda: (PYFMI_JACOBIAN_LIMIT-1, 0) opts["with_jacobian"] = True run_case(True, True)
def test_correct_file_after_simulation_failure(self): simple_alias = Dummy_FMUModelME2([("x", "y")], "NegatedAlias.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) def f(*args, **kwargs): if simple_alias.time > 0.5: raise Exception return -simple_alias.continuous_states simple_alias.get_derivatives = f opts = simple_alias.simulate_options() opts["result_handling"] = "file" opts["solver"] = "ExplicitEuler" successful_simulation = False try: res = simple_alias.simulate(options=opts) successful_simulation = True #The above simulation should fail... except: pass if successful_simulation: raise Exception result = ResultDymolaTextual("NegatedAlias_result.txt") x = result.get_variable_data("x").x y = result.get_variable_data("y").x assert len(x) > 2 for i in range(len(x)): nose.tools.assert_equal(x[i], -y[i])
def test_maxh_option(self): model = Dummy_FMUModelME2([], "NoState.Example1.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = model.simulate_options() opts["result_handling"] = "none" from pyfmi.fmi_algorithm_drivers import AssimuloFMIAlg class TempAlg(AssimuloFMIAlg): def solve(self): pass def run_case(tstart, tstop, solver, ncp="Default"): model.reset() opts["solver"] = solver if ncp != "Default": opts["ncp"] = ncp if opts["ncp"] == 0: expected = 0.0 else: expected = (float(tstop)-float(tstart))/float(opts["ncp"]) res = model.simulate(start_time=tstart, final_time=tstop,options=opts, algorithm=TempAlg) assert res.solver.maxh == expected, res.solver.maxh assert res.options[solver+"_options"]["maxh"] == "Default", res.options[solver+"_options"]["maxh"] run_case(0,1,"CVode") run_case(0,1,"CVode", 0) run_case(0,1,"Radau5ODE") run_case(0,1,"Dopri5") run_case(0,1,"RodasODE") run_case(0,1,"LSODAR") run_case(0,1,"LSODAR")
def test_estimate_directional_derivatives_linearstate(self): full_path = os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "LinearStateSpace.fmu") model = Dummy_FMUModelME2([], full_path, _connect_dll=False) def f(*args, **kwargs): derx1 = -1.*model.values[model.variables["x[1]"].value_reference] + model.values[model.variables["u[1]"].value_reference] derx2 = -1.*model.values[model.variables["x[2]"].value_reference] + model.values[model.variables["u[1]"].value_reference] model.values[model.variables["y[1]"].value_reference] = model.values[model.variables["x[1]"].value_reference] + model.values[model.variables["x[2]"].value_reference] return np.array([derx1, derx2]) model.get_derivatives = f model.initialize() model.event_update() model.enter_continuous_time_mode() [As, Bs, Cs, Ds] = model.get_state_space_representation(use_structure_info=False) [A, B, C, D] = model.get_state_space_representation() assert As.shape == A.shape, str(As.shape)+' '+str(A.shape) assert Bs.shape == B.shape, str(Bs.shape)+' '+str(B.shape) assert Cs.shape == C.shape, str(Cs.shape)+' '+str(C.shape) assert Ds.shape == D.shape, str(Ds.shape)+' '+str(D.shape) assert np.allclose(As, A.toarray()), str(As)+' '+str(A.toarray()) assert np.allclose(Bs, B.toarray()), str(Bs)+' '+str(B.toarray()) assert np.allclose(Cs, C.toarray()), str(Cs)+' '+str(C.toarray()) assert np.allclose(Ds, D.toarray()), str(Ds)+' '+str(D.toarray())
def test_get_directional_derivative_capability(self): bounce = Dummy_FMUModelME2([], "bouncingBall.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) bounce.setup_experiment() bounce.initialize() # Bouncing ball don't have the capability, check that this is handled nose.tools.assert_raises(FMUException, bounce.get_directional_derivative, [1], [1], [1]) bounce = Dummy_FMUModelCS2([], "bouncingBall.fmu", os.path.join(file_path, "files", "FMUs", "XML", "CS2.0"), _connect_dll=False) bounce.setup_experiment() bounce.initialize() # Bouncing ball don't have the capability, check that this is handled nose.tools.assert_raises(FMUException, bounce.get_directional_derivative, [1], [1], [1])
def test_basicsens2(self): model = Dummy_FMUModelME2([], "BasicSens2.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) caps = model.get_capability_flags() caps["providesDirectionalDerivatives"] = True model.get_capability_flags = lambda: caps def f(*args, **kwargs): d = model.values[model.variables["d"].value_reference] x = model.continuous_states[0] model.values[model.variables["der(x)"].value_reference] = d * x return np.array([d * x]) def d(*args, **kwargs): if args[0][0] == 40: return np.array([-1.0]) else: return model.continuous_states model.get_directional_derivative = d model.get_derivatives = f model._provides_directional_derivatives = lambda: True opts = model.simulate_options() opts["sensitivities"] = ["d"] res = model.simulate(options=opts) nose.tools.assert_almost_equal(res.final('dx/dd'), 0.36789, 3) assert res.solver.statistics["nsensfcnfcns"] == 0
def test_work_flow_me2(self): model = Dummy_FMUModelME2([], "bouncingBall.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) model.setup_experiment() model.initialize() bouncingBall = ResultHandlerCSV(model) bouncingBall.set_options(model.simulate_options()) bouncingBall.simulation_start() bouncingBall.initialize_complete() bouncingBall.integration_point() bouncingBall.simulation_end() res = ResultCSVTextual('bouncingBall_result.csv') h = res.get_variable_data('h') derh = res.get_variable_data('der(h)') g = res.get_variable_data('g') nose.tools.assert_almost_equal(h.x, 1.000000, 5) nose.tools.assert_almost_equal(derh.x, 0.000000, 5)
def test_estimate_directional_derivatives_without_structure_info(self): full_path = os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "Bouncing_Ball.fmu") model = Dummy_FMUModelME2([], full_path, _connect_dll=False) def f(*args, **kwargs): derh = model.values[model.variables["v"].value_reference] derv = -9.81 model.values[model.variables["der(h)"].value_reference] = derh return np.array([derh, derv]) model.get_derivatives = f model.initialize() model.event_update() model.enter_continuous_time_mode() [As, Bs, Cs, Ds] = model.get_state_space_representation(use_structure_info=False) [A, B, C, D] = model.get_state_space_representation() assert As.shape == A.shape, str(As.shape) + ' ' + str(A.shape) assert Bs.shape == B.shape, str(Bs.shape) + ' ' + str(B.shape) assert Cs.shape == C.shape, str(Cs.shape) + ' ' + str(C.shape) assert Ds.shape == D.shape, str(Ds.shape) + ' ' + str(D.shape) assert np.allclose(As, A.toarray()), str(As) + ' ' + str(A.toarray()) assert np.allclose(Bs, B.toarray()), str(Bs) + ' ' + str(B.toarray()) assert np.allclose(Cs, C.toarray()), str(Cs) + ' ' + str(C.toarray()) assert np.allclose(Ds, D.toarray()), str(Ds) + ' ' + str(D.toarray())
def _test_logging_different_solver(self, solver_name): model = Dummy_FMUModelME2([], "Bouncing_Ball.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = model.simulate_options() opts["dynamic_diagnostics"] = True opts["solver"] = solver_name res = model.simulate(options=opts) res_vars = res.keys() full_solver_name = f"{diagnostics_prefix}solver.solver_name.{solver_name}" assert full_solver_name in res_vars, f"Missing {full_solver_name} in results!" assert f"{diagnostics_prefix}step_time" in res_vars, f"Missing {diagnostics_prefix}step_time in results!" np.testing.assert_equal( res[f'{diagnostics_prefix}step_time'], res['time'], f"Expected {diagnostics_prefix}step_time and time to be equal but they weren't!" ) np.testing.assert_equal( len(res[f'{diagnostics_prefix}cpu_time']), len(res['time']), f"Expected {diagnostics_prefix}cpu_time and time to be of equal length but they weren't!" ) assert np.all( np.diff(res[f'{diagnostics_prefix}nbr_steps']) >= 0 ), "Expected cumulative number of steps to increase, but wasn't!" np.testing.assert_equal( len(res[f'{diagnostics_prefix}nbr_steps']), len(res['time']), f"Expected {diagnostics_prefix}cpu_time and time to be of equal length but they weren't!" ) np.testing.assert_equal( len(res['time']), len(res['h']), "Expected time and h to be of equal length but they weren't!") return res
def test_integer_start_time(self): model = Dummy_FMUModelME2([], "Alias.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = model.simulate_options() opts["result_handling"] = "binary" #Assert that there is no exception when reloading the file res = model.simulate(start_time=0, options=opts)
def test_ncp_option(self): model = Dummy_FMUModelME2([], "NoState.Example1.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = model.simulate_options() assert opts["ncp"] == 500, opts["ncp"]
def test_csv_options_me2(self): simple_alias = Dummy_FMUModelME2([("x", "y")], "NegatedAlias.fmu", os.path.join( file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) _run_negated_alias(simple_alias, "csv")
def test_relative_tolerance(self): model = Dummy_FMUModelME2([], "NoState.Example1.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = model.simulate_options() opts["CVode_options"]["rtol"] = 1e-8 res = model.simulate(options=opts) assert res.options["CVode_options"]["atol"] == 1e-10
def test_maxord_is_set(self): model = Dummy_FMUModelME2([], "NoState.Example1.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = model.simulate_options() opts["solver"] = "CVode" opts["CVode_options"]["maxord"] = 1 res = model.simulate(final_time=1.5,options=opts) assert res.solver.maxord == 1
def test_estimate_directional_derivatives_BCD(self): full_path = os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "OutputTest2.fmu") model = Dummy_FMUModelME2([], full_path, _connect_dll=False) def f(*args, **kwargs): x1 = model.values[model.variables["x1"].value_reference] x2 = model.values[model.variables["x2"].value_reference] u1 = model.values[model.variables["u1"].value_reference] model.values[model.variables["y1"].value_reference] = x1 * x2 - u1 model.values[model.variables["y2"].value_reference] = x2 model.values[model.variables["y3"].value_reference] = u1 + x1 model.values[model.variables["der(x1)"].value_reference] = -1.0 model.values[model.variables["der(x2)"].value_reference] = -1.0 model.get_derivatives = f model.initialize() model.event_update() model.enter_continuous_time_mode() for func in [model._get_B, model._get_C, model._get_D]: A = func(use_structure_info=True) B = func(use_structure_info=True, output_matrix=A) assert A is B #Test that the returned matrix is actually the same as the input assert np.allclose(A.toarray(), B.toarray()) A = func(use_structure_info=False) B = func(use_structure_info=False, output_matrix=A) assert A is B assert np.allclose(A, B) C = func(use_structure_info=True, output_matrix=A) assert A is not C assert np.allclose(C.toarray(), A) D = func(use_structure_info=False, output_matrix=C) assert D is not C assert np.allclose(D, C.toarray()) B = model._get_B(use_structure_info=True) C = model._get_C(use_structure_info=True) D = model._get_D(use_structure_info=True) assert np.allclose(B.toarray(), np.array([[0.0], [0.0]])) assert np.allclose(C.toarray(), np.array([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0]])) assert np.allclose(D.toarray(), np.array([[-1.0], [0.0], [1.0]])) B = model._get_B(use_structure_info=False) C = model._get_C(use_structure_info=False) D = model._get_D(use_structure_info=False) assert np.allclose(B, np.array([[0.0], [0.0]])) assert np.allclose(C, np.array([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0]])) assert np.allclose(D, np.array([[-1.0], [0.0], [1.0]]))
def test_only_parameters(self): model = Dummy_FMUModelME2([], "ParameterAlias.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = model.simulate_options() opts["result_handling"] = "custom" opts["result_handler"] = ResultHandlerCSV(model) opts["filter"] = "p2" res = model.simulate(options=opts) nose.tools.assert_almost_equal(3.0, res["p2"][0])
def test_solver_options_using_defaults(self): model = Dummy_FMUModelME2([], "NoState.Example1.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = model.simulate_options() opts["CVode_options"] = {"maxh":1.0} assert opts["CVode_options"]["atol"] == "Default", "Default should have been changed: " + opts["CVode_options"]["atol"] assert opts["CVode_options"]["maxh"] == 1.0, "Value should have been changed to 1.0: " + opts["CVode_options"]["maxh"] opts["CVode_options"] = {"atol":1e-6} #Defaults should be used together with only the option atol set assert opts["CVode_options"]["atol"] == 1e-6, "Default should have been changed: " + opts["CVode_options"]["atol"] assert opts["CVode_options"]["maxh"] == "Default", "Value should have been default is: " + opts["CVode_options"]["maxh"]
def test_read_all_variables_using_model_variables(self): simple_alias = Dummy_FMUModelME2([("x", "y")], "NegatedAlias.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = simple_alias.simulate_options() opts["result_handling"] = "custom" opts["result_handler"] = ResultHandlerFile(simple_alias) res = simple_alias.simulate(options=opts) for var in simple_alias.get_model_variables(): res[var]
def test_simulate_with_debug_option_no_state(self): model = Dummy_FMUModelME2([], "NoState.Example1.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts=model.simulate_options() opts["logging"] = True #Verify that a simulation is successful res=model.simulate(options=opts) from pyfmi.debug import CVodeDebugInformation debug = CVodeDebugInformation("NoState_Example1_debug.txt")
def test_only_parameters(self): model = Dummy_FMUModelME2([], "ParameterAlias.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = model.simulate_options() opts["result_handling"] = "memory" opts["filter"] = "p2" res = model.simulate(options=opts) nose.tools.assert_almost_equal(3.0, res["p2"][0]) assert not isinstance(res.initial("p2"), np.ndarray) assert not isinstance(res.final("p2"), np.ndarray)
def test_enumeration_memory(self): model = Dummy_FMUModelME2([], "Friction2.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) data_type = model.get_variable_data_type("mode") assert data_type == fmi.FMI2_ENUMERATION opts = model.simulate_options() opts["result_handling"] = "memory" res = model.simulate(options=opts) res["mode"] #Check that the enumeration variable is in the dict, otherwise exception
def test_simulation_without_initialization(self): model = Dummy_FMUModelME2([], "bouncingBall.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = model.simulate_options() opts["initialize"] = False nose.tools.assert_raises(FMUException, model.simulate, options=opts) model = Dummy_FMUModelCS2([], "bouncingBall.fmu", os.path.join(file_path, "files", "FMUs", "XML", "CS2.0"), _connect_dll=False) opts = model.simulate_options() opts["initialize"] = False nose.tools.assert_raises(FMUException, model.simulate, options=opts)
def _test_logging_different_solver(self, solver_name): model = Dummy_FMUModelME2([], "Bouncing_Ball.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = model.simulate_options() opts["logging"] = True opts["solver"] = solver_name model.simulate(options=opts) log_file = model.extract_xml_log() assert os.path.exists(log_file), "Missing log file for {}".format( solver_name)
def test_read_alias_derivative(self): simple_alias = Dummy_FMUModelME2([], "Alias.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = simple_alias.simulate_options() opts["result_handling"] = "binary" res = simple_alias.simulate(options=opts) derx = res["der(x)"] dery = res["der(y)"] for i in range(len(derx)): nose.tools.assert_equal(derx[i], dery[i])
def test_solver_options(self): model = Dummy_FMUModelME2([], "NoState.Example1.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = model.simulate_options() try: opts["CVode_options"] = "ShouldFail" raise Exception("Setting an incorrect option should lead to exception being thrown, it wasn't") except UnrecognizedOptionError: pass opts["CVode_options"] = {"maxh":1.0} assert opts["CVode_options"]["atol"] == "Default", "Default should have been changed: " + opts["CVode_options"]["atol"] assert opts["CVode_options"]["maxh"] == 1.0, "Value should have been changed to 1.0: " + opts["CVode_options"]["maxh"]
def test_no_variables(self): model = Dummy_FMUModelME2([], "ParameterAlias.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = model.simulate_options() opts["result_handling"] = "memory" opts["filter"] = "NoMatchingVariables" res = model.simulate(options=opts) nose.tools.assert_almost_equal(1.0, res["time"][-1])
def test_variable_alias_custom_handler(self): simple_alias = Dummy_FMUModelME2([("x", "y")], "NegatedAlias.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) opts = simple_alias.simulate_options() opts["result_handling"] = "custom" opts["result_handler"] = ResultHandlerBinaryFile(simple_alias) res = simple_alias.simulate(options=opts) # test that res['y'] returns a vector of the same length as the time # vector nose.tools.assert_equal(len(res['y']),len(res['time']), "Wrong size of result vector.") x = res["x"] y = res["y"] for i in range(len(x)): nose.tools.assert_equal(x[i], -y[i])
def test_basicsens1(self): #Noncompliant FMI test as 'd' is parameter is not supposed to be able to be set during simulation model = Dummy_FMUModelME2([], "BasicSens1.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) def f(*args, **kwargs): d = model.values[model.variables["d"].value_reference] x = model.continuous_states[0] model.values[model.variables["der(x)"].value_reference] = d*x return np.array([d*x]) model.get_derivatives = f opts = model.simulate_options() opts["sensitivities"] = ["d"] res = model.simulate(options=opts) nose.tools.assert_almost_equal(res.final('dx/dd'), 0.36789, 3) assert res.solver.statistics["nsensfcnfcns"] > 0
def test_filter_no_variables(self): model = Dummy_FMUModelME2([], "bouncingBall.fmu", os.path.join(file_path, "files", "FMUs", "XML", "ME2.0"), _connect_dll=False) model.setup_experiment() model.initialize() model.time = 1.0 opts = model.simulate_options() opts["filter"] = "NoMatchingVariables" bouncingBall = ResultHandlerBinaryFile(model) bouncingBall.set_options(opts) bouncingBall.simulation_start() bouncingBall.initialize_complete() bouncingBall.integration_point() bouncingBall.simulation_end() res = ResultDymolaBinary('bouncingBall_result.mat') t = res.get_variable_data('time') nose.tools.assert_almost_equal(t.x[-1], 1.000000, 5)