Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
--- CHANGELOG ---
--- PyFMI-FUTURE ---
* Fixed a crash with the `Master` algorithm option `block_initialization`.

--- PyFMI-2.20.0 ---
* Fixed so FMU `reset` resets to log_level that it was loaded with.
Expand Down
12 changes: 12 additions & 0 deletions src/pyfmi/master.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,9 @@ cdef class Master:
return xd

cpdef np.ndarray get_specific_connection_outputs_discrete(self, model, np.ndarray mask, np.ndarray yout):
if len(mask) == 0:
# quick return; nothing to get; prevents index array in array slicing
return
cdef int j = 0
ytmp = model.get(np.array(self.models_dict[model]["local_output_discrete"])[mask])
for i, flag in enumerate(mask):
Expand All @@ -883,6 +886,9 @@ cdef class Master:
j = j + 1

cpdef np.ndarray get_specific_connection_outputs(self, model, np.ndarray mask, np.ndarray yout):
if len(mask) == 0:
# quick return; nothing to get; prevents index array in array slicing
return
cdef int j = 0
cdef np.ndarray ytmp = (<FMI2.FMUModelCS2>model).get_real(self.models_dict[model]["local_output_vref_array"][mask])
for i, flag in enumerate(mask):
Expand Down Expand Up @@ -1015,6 +1021,9 @@ cdef class Master:
model.set(self.models_dict[model]["local_input_discrete"], u[i:inext])

cpdef set_specific_connection_inputs(self, model, np.ndarray mask, np.ndarray u):
if len(mask) == 0:
# quick return; nothing to set; prevents index array in array slicing
return
cdef int i = self.models_dict[model]["global_index_inputs"]
cdef int inext = i + self.models_dict[model]["local_input_len"]
cdef np.ndarray usliced = u[i:inext]
Expand All @@ -1023,6 +1032,9 @@ cdef class Master:
(<FMI2.FMUModelCS2>model).set_real(self.models_dict[model]["local_input_vref_array"][mask], usliced[mask])

cpdef set_specific_connection_inputs_discrete(self, model, np.ndarray mask, np.ndarray u):
if len(mask) == 0:
# quick return; nothing to set; prevents index array in array slicing
return
cdef int i = self.models_dict[model]["global_index_inputs_discrete"]
cdef int inext = i + self.models_dict[model]["local_input_discrete_len"]
cdef np.ndarray usliced = u[i:inext]
Expand Down
18 changes: 18 additions & 0 deletions tests/test_fmi_master.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,24 @@ def test_external_inputs(self, input_traj):
np.testing.assert_array_equal(res[0]["Float64_discrete_output"], [0, 0, 0, 0, 0, 0])
np.testing.assert_array_equal(res[1]["Float64_discrete_output"], [0, 2, 4, 6, 8, 10])

def test_block_initialization(self):
"""Basic smoke-test for the 'block_initialization' option."""
fmu1 = FMUModelCS2(os.path.join(FMI2_REF_FMU_PATH, "Feedthrough.fmu"))
fmu2 = FMUModelCS2(os.path.join(FMI2_REF_FMU_PATH, "Feedthrough.fmu"))
fmu3 = FMUModelCS2(os.path.join(FMI2_REF_FMU_PATH, "Feedthrough.fmu"))

models = [fmu1, fmu2, fmu3]
# some inputs/outputs are intentionally left unconnected
connections = [
(fmu1, "Float64_continuous_output", fmu2, "Float64_continuous_input"),
(fmu2, "Float64_discrete_output", fmu3, "Float64_discrete_input"),
]
master = Master(models, connections)

opts = master.simulate_options()
opts["block_initialization"] = True
master.simulate(0, 1, options=opts)

class Test_Master_Result_Downsampling:
"""Tests related to the 'result_downsampling' option of the Master algorithm."""
@classmethod
Expand Down