diff --git a/src/pyfmi/fmi.pxd b/src/pyfmi/fmi.pxd index be1988e9..b4caf933 100644 --- a/src/pyfmi/fmi.pxd +++ b/src/pyfmi/fmi.pxd @@ -207,7 +207,7 @@ cdef class FMUModelBase2(ModelBase): cdef object _outputs_states_dependencies_kind cdef object _outputs_inputs_dependencies_kind cdef object _A, _B, _C, _D - cdef public object _group_A, _group_B, _group_C, _group_D + cdef public object _group_A, _group_B, _group_C, _group_D cdef object _mask_A cdef object _A_row_ind, _A_col_ind cdef public object _has_entered_init_mode diff --git a/tests/test_fmi.py b/tests/test_fmi.py index dc8053de..3b46e907 100644 --- a/tests/test_fmi.py +++ b/tests/test_fmi.py @@ -1191,16 +1191,19 @@ def test_estimate_directional_derivatives_BCD(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "OutputTest2.fmu"), _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 + x1 = model.get_real([model.variables["x1"].value_reference], evaluate = False) + x2 = model.get_real([model.variables["x2"].value_reference], evaluate = False) + u1 = model.get_real([model.variables["u1"].value_reference], evaluate = False) + + model.set_real([model.variables["y1"].value_reference], x1*x2 - u1) + model.set_real([model.variables["y2"].value_reference], x2) + model.set_real([model.variables["y3"].value_reference], u1 + x1) + + dx1 = -1.0 + dx2 = -1.0 + model.set_real([model.variables["der(x1)"].value_reference], [dx1]) + model.set_real([model.variables["der(x2)"].value_reference], [dx2]) + return np.array([dx1, dx2]) model.get_derivatives = f model.initialize() @@ -1227,17 +1230,17 @@ def f(*args, **kwargs): 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]])) + assert np.allclose(B.toarray(), np.array([[0.0], [0.0]])), str(B.toarray()) + assert np.allclose(C.toarray(), np.array([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0]])), str(C.toarray()) + assert np.allclose(D.toarray(), np.array([[-1.0], [0.0], [1.0]])), str(D.toarray()) 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]])) + assert np.allclose(B, np.array([[0.0], [0.0]])), str(B.toarray()) + assert np.allclose(C, np.array([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0]])), str(C.toarray()) + assert np.allclose(D, np.array([[-1.0], [0.0], [1.0]])), str(D.toarray()) @testattr(stddist = True) def test_output_dependencies(self): diff --git a/tests/test_fmi_coupled.py b/tests/test_fmi_coupled.py index 2fe809cb..d0b26f88 100644 --- a/tests/test_fmi_coupled.py +++ b/tests/test_fmi_coupled.py @@ -46,26 +46,26 @@ def test_linear_example(self): model_sub_2 = Dummy_FMUModelME2([], os.path.join(me2_xml_path, "LinearStability.SubSystem2.fmu"), _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")] + u1 = model_sub_1.get_real([model_sub_1.get_variable_valueref("u1")], evaluate = False) + a1 = model_sub_1.get_real([model_sub_1.get_variable_valueref("a1")], evaluate = False) + b1 = model_sub_1.get_real([model_sub_1.get_variable_valueref("b1")], evaluate = False) + c1 = model_sub_1.get_real([model_sub_1.get_variable_valueref("c1")], evaluate = False) + d1 = model_sub_1.get_real([model_sub_1.get_variable_valueref("d1")], evaluate = False) 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]) + model_sub_1.set_real([model_sub_1.get_variable_valueref("y1")], c1*x1+d1*u1) + model_sub_1.set_real([model_sub_1.get_variable_valueref("x1")], [x1]) + return 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")] + u2 = model_sub_2.get_real([model_sub_2.get_variable_valueref("u2")], evaluate = False) + a2 = model_sub_2.get_real([model_sub_2.get_variable_valueref("a2")], evaluate = False) + b2 = model_sub_2.get_real([model_sub_2.get_variable_valueref("b2")], evaluate = False) + c2 = model_sub_2.get_real([model_sub_2.get_variable_valueref("c2")], evaluate = False) + d2 = model_sub_2.get_real([model_sub_2.get_variable_valueref("d2")], evaluate = False) 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_2.set_real([model_sub_2.get_variable_valueref("y2")], c2*x2+d2*u2) + model_sub_2.set_real([model_sub_2.get_variable_valueref("x2")], [x2]) + return a2*x2+b2*u2 model_sub_1.get_derivatives = sub1 model_sub_2.get_derivatives = sub2 diff --git a/tests/test_fmi_estimate.py b/tests/test_fmi_estimate.py index f4377bc9..0f438c09 100644 --- a/tests/test_fmi_estimate.py +++ b/tests/test_fmi_estimate.py @@ -37,17 +37,17 @@ class Test_FMUModelME2_Estimate: def test_quadtank_estimate(self): model = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "QuadTankPack_Sim_QuadTank.fmu"), _connect_dll=False) - g = model.values[model.get_variable_valueref("qt.g")] - g1_nmp = model.values[model.get_variable_valueref("qt.g1_nmp")] - g2_nmp = model.values[model.get_variable_valueref("qt.g2_nmp")] - k1_nmp = model.values[model.get_variable_valueref("qt.k1_nmp")] - k2_nmp = model.values[model.get_variable_valueref("qt.k2_nmp")] - A1 = model.values[model.get_variable_valueref("qt.A1")] - A2 = model.values[model.get_variable_valueref("qt.A2")] - A3 = model.values[model.get_variable_valueref("qt.A3")] - A4 = model.values[model.get_variable_valueref("qt.A4")] - a3 = model.values[model.get_variable_valueref("qt.a3")] - a4 = model.values[model.get_variable_valueref("qt.a4")] + g = model.get_real([model.get_variable_valueref("qt.g")], evaluate = False) + g1_nmp = model.get_real([model.get_variable_valueref("qt.g1_nmp")], evaluate = False) + g2_nmp = model.get_real([model.get_variable_valueref("qt.g2_nmp")], evaluate = False) + k1_nmp = model.get_real([model.get_variable_valueref("qt.k1_nmp")], evaluate = False) + k2_nmp = model.get_real([model.get_variable_valueref("qt.k2_nmp")], evaluate = False) + A1 = model.get_real([model.get_variable_valueref("qt.A1")], evaluate = False) + A2 = model.get_real([model.get_variable_valueref("qt.A2")], evaluate = False) + A3 = model.get_real([model.get_variable_valueref("qt.A3")], evaluate = False) + A4 = model.get_real([model.get_variable_valueref("qt.A4")], evaluate = False) + a3 = model.get_real([model.get_variable_valueref("qt.a3")], evaluate = False) + a4 = model.get_real([model.get_variable_valueref("qt.a4")], evaluate = False) u1_vref = model.get_variable_valueref("u1") u2_vref = model.get_variable_valueref("u2") a1_vref = model.get_variable_valueref("qt.a1") @@ -59,18 +59,16 @@ def f(*args, **kwargs): x3 = model.continuous_states[2] x4 = model.continuous_states[3] - u1 = model.values[u1_vref] - u2 = model.values[u2_vref] - a1 = model.values[a1_vref] - a2 = model.values[a2_vref] + u1 = model.get_real([u1_vref], evaluate = False) + u2 = model.get_real([u2_vref], evaluate = False) + a1 = model.get_real([a1_vref], evaluate = False) + a2 = model.get_real([a2_vref], evaluate = False) - sqrt = lambda x: (x)**0.5 - der_x1 = -a1/A1*sqrt(2.*g*x1) + a3/A1*sqrt(2*g*x3) + g1_nmp*k1_nmp/A1*u1 - der_x2 = -a2/A2*sqrt(2.*g*x2) + a4/A2*sqrt(2*g*x4) + g2_nmp*k2_nmp/A2*u2 - der_x3 = -a3/A3*sqrt(2.*g*x3) + (1.-g2_nmp)*k2_nmp/A3*u2 - der_x4 = -a4/A4*sqrt(2.*g*x4) + (1.-g1_nmp)*k1_nmp/A4*u1 - return np.array([der_x1, der_x2, der_x3, der_x4]) - + der_x1 = -a1/A1*np.sqrt(2.*g*x1) + a3/A1*np.sqrt(2*g*x3) + g1_nmp*k1_nmp/A1*u1 + der_x2 = -a2/A2*np.sqrt(2.*g*x2) + a4/A2*np.sqrt(2*g*x4) + g2_nmp*k2_nmp/A2*u2 + der_x3 = -a3/A3*np.sqrt(2.*g*x3) + (1.-g2_nmp)*k2_nmp/A3*u2 + der_x4 = -a4/A4*np.sqrt(2.*g*x4) + (1.-g1_nmp)*k1_nmp/A4*u1 + return np.concatenate([der_x1, der_x2, der_x3, der_x4]) model.get_derivatives = f @@ -90,7 +88,7 @@ def f(*args, **kwargs): u = np.transpose(np.vstack((t_meas,u1,u2))) # Estimation of 2 parameters - data = np.vstack((t_meas, y1_meas,y2_meas)).transpose() + data = np.vstack((t_meas, y1_meas, y2_meas)).transpose() res = model.estimate(parameters=["qt.a1", "qt.a2"], measurements = (['qt.x1', 'qt.x2'], data), input=(['u1','u2'],u)) @@ -99,11 +97,11 @@ def f(*args, **kwargs): model.reset() # Set optimal values for a1 and a2 into the model - model.set('qt.a1',res["qt.a1"]) - model.set('qt.a2',res["qt.a2"]) + model.set(['qt.a1'], res["qt.a1"]) + model.set(['qt.a2'], res["qt.a2"]) # Simulate model response with optimal parameters a1 and a2 - res = model.simulate(input=(['u1','u2'],u),start_time=0.,final_time=60) + res = model.simulate(input=(['u1','u2'], u), start_time=0., final_time=60) assert np.abs(res.final('qt.x1') - 0.07060188) < 1e-3, "Was: " + str(res.final('qt.x1')) + ", expected: 0.07060188" assert np.abs(res.final('qt.x2') - 0.06654621) < 1e-3 diff --git a/tests/test_fmi_master.py b/tests/test_fmi_master.py index 80147f08..811c4b01 100644 --- a/tests/test_fmi_master.py +++ b/tests/test_fmi_master.py @@ -118,7 +118,7 @@ def do_step1(current_t, step_size, new_step=True): u1 = model_sub1.values[model_sub1.get_variable_valueref("u1")] model_sub1.continuous_states = 1.0/a1*(np.exp(a1*step_size)-1.0)*b1*u1+np.exp(a1*step_size)*model_sub1.continuous_states - model_sub1.values[model_sub1.get_variable_valueref("y1")] = c1*model_sub1.continuous_states+d1*u1 + model_sub1.set_real([model_sub1.get_variable_valueref("y1")], c1*model_sub1.continuous_states+d1*u1) model_sub1.completed_integrator_step() return 0 @@ -126,7 +126,7 @@ def do_step2(current_t, step_size, new_step=True): u2 = model_sub2.values[model_sub2.get_variable_valueref("u2")] model_sub2.continuous_states = 1.0/a2*(np.exp(a2*step_size)-1.0)*b2*u2+np.exp(a2*step_size)*model_sub2.continuous_states - model_sub2.values[model_sub2.get_variable_valueref("y2")] = c2*model_sub2.continuous_states+d2*u2 + model_sub2.set_real([model_sub2.get_variable_valueref("y2")], c2*model_sub2.continuous_states+d2*u2) model_sub2.completed_integrator_step() return 0 @@ -219,13 +219,13 @@ def test_integer_connections(self): model_sub1.set("y", 1) def do_step1(current_t, step_size, new_step=True): - model_sub1.values[model_sub1.get_variable_valueref("y")] = 1 if current_t+step_size < 0.5 else 3 + model_sub1.set_integer([model_sub1.get_variable_valueref("y")], [1] if current_t+step_size < 0.5 else [3]) model_sub1.completed_integrator_step() return 0 def do_step2(current_t, step_size, new_step=True): - u = model_sub2.values[model_sub2.get_variable_valueref("u")] - model_sub2.values[model_sub2.get_variable_valueref("y")] = 10*u + u = model_sub2.get_integer([model_sub2.get_variable_valueref("u")]) + model_sub2.set_integer([model_sub2.get_variable_valueref("y")], 10*u) model_sub2.completed_integrator_step() return 0 @@ -252,13 +252,13 @@ def test_integer_to_real_connections(self): model_sub1.set("y", 1) def do_step1(current_t, step_size, new_step=True): - model_sub1.values[model_sub1.get_variable_valueref("y")] = 1 if current_t+step_size < 0.5 else 3 + model_sub1.set_integer([model_sub1.get_variable_valueref("y")], [1] if current_t+step_size < 0.5 else [3]) model_sub1.completed_integrator_step() return 0 def do_step2(current_t, step_size, new_step=True): - u = model_sub2.values[model_sub2.get_variable_valueref("u")] - model_sub2.values[model_sub2.get_variable_valueref("y")] = 10*u + u = model_sub2.get_real([model_sub2.get_variable_valueref("u")]) + model_sub2.set_real([model_sub2.get_variable_valueref("y")], 10*u) model_sub2.completed_integrator_step() return 0 @@ -299,7 +299,7 @@ def do_step1(current_t, step_size, new_step=True): u1 = model_sub1.values[model_sub1.get_variable_valueref("u1")] model_sub1.continuous_states = 1.0/a1*(np.exp(a1*step_size)-1.0)*b1*u1+np.exp(a1*step_size)*model_sub1.continuous_states - model_sub1.values[model_sub1.get_variable_valueref("y1")] = c1*model_sub1.continuous_states+d1*u1 + model_sub1.set_real([model_sub1.get_variable_valueref("y1")], c1*model_sub1.continuous_states+d1*u1) model_sub1.completed_integrator_step() return 0 @@ -307,7 +307,7 @@ def do_step2(current_t, step_size, new_step=True): u2 = model_sub2.values[model_sub2.get_variable_valueref("u2")] model_sub2.continuous_states = 1.0/a2*(np.exp(a2*step_size)-1.0)*b2*u2+np.exp(a2*step_size)*model_sub2.continuous_states - model_sub2.values[model_sub2.get_variable_valueref("y2")] = c2*model_sub2.continuous_states+d2*u2 + model_sub2.set_real([model_sub2.get_variable_valueref("y2")], c2*model_sub2.continuous_states+d2*u2) model_sub2.completed_integrator_step() return 0 diff --git a/tests/test_util.py b/tests/test_util.py index 41403ab7..b87abf04 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -24,16 +24,6 @@ def get_examples_folder(): return os.path.join(os.path.dirname(__file__), '..', 'examples') -class _ValuesDict(dict): - """Auxiliary dictionary that converts np.array() inputs of length 1 to simple numbers.""" - def __setitem__(self, key, value): - if hasattr(value, "__len__"): - if len(value) > 1: - raise KeyError("expected value of length 1") - self.__setitem__(key, value[0]) - else: - super().__setitem__(key, value) - class Dummy_FMUModelME1(_ForTestingFMUModelME1): # If true, makes use of the real _ForTesting implementation for nominal_continuous_states, # else just returns 1.0 for each. @@ -52,7 +42,7 @@ def __init__(self, states_vref, *args,**kwargs): self.variables = self.get_model_variables(include_alias=False) self.states_vref = states_vref - self.values = _ValuesDict() + self.values = {} for var in self.variables: try: start = self.get_variable_start(var) @@ -110,7 +100,7 @@ def __init__(self, states_vref, *args,**kwargs): self.variables = self.get_model_variables(include_alias=False) self.states_vref = states_vref - self.values = _ValuesDict() + self.values = {} for var in self.variables: try: start = self.get_variable_start(var) @@ -149,7 +139,7 @@ def __init__(self, negated_aliases, *args,**kwargs): self.variables = self.get_model_variables(include_alias=False) self.negated_aliases = negated_aliases - self.values = _ValuesDict() + self.values = {} for var in self.variables: try: start = self.get_variable_start(var) @@ -245,7 +235,7 @@ def __init__(self, negated_aliases, *args, **kwargs): self.reset() def reset(self, *args, **kwargs): - self.values = _ValuesDict() + self.values = {} for var in self.variables: try: start = self.get_variable_start(var) @@ -294,8 +284,9 @@ def completed_integrator_step(self, *args, **kwargs): def get_derivatives(self): return -self.continuous_states - def get_real(self, vref): - self.get_derivatives() + def get_real(self, vref, evaluate = True): + if evaluate: + self.get_derivatives() vals = [] if type(vref) == int: vref = [vref]