Skip to content

Commit

Permalink
Properly fixed various examples
Browse files Browse the repository at this point in the history
  • Loading branch information
PeterMeisrimelModelon committed Jan 25, 2024
1 parent bdd73ac commit c4df249
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 85 deletions.
2 changes: 1 addition & 1 deletion src/pyfmi/fmi.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
35 changes: 19 additions & 16 deletions tests/test_fmi.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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):
Expand Down
32 changes: 16 additions & 16 deletions tests/test_fmi_coupled.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
50 changes: 24 additions & 26 deletions tests/test_fmi_estimate.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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

Expand All @@ -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))
Expand All @@ -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
Expand Down
20 changes: 10 additions & 10 deletions tests/test_fmi_master.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,15 @@ 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

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

Expand Down Expand Up @@ -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

Expand All @@ -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

Expand Down Expand Up @@ -299,15 +299,15 @@ 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

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

Expand Down
23 changes: 7 additions & 16 deletions tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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]
Expand Down

0 comments on commit c4df249

Please sign in to comment.