Skip to content
Merged
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
2 changes: 2 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
--- PyFMI-FUTURE ---
* Fixed a crash with the `Master` algorithm option `block_initialization`.
* Fixed a result handling issue for `dynamic_diagnostics = True` and `["<solver>_options"]["clock_step"] = False`.
* Fixed an issue for the `Master` algorithm where connection values could be initialized incorrectly, when FMUs
were initialized separately and using `step_size_downsampling_factor`.

--- PyFMI-2.20.1 ---
* Resolved issue where caching in result handling was too persistent and could prevent automatic garbage collection.
Expand Down
11 changes: 6 additions & 5 deletions src/pyfmi/master.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1253,10 +1253,6 @@ cdef class Master:

exit_initialization_mode(self.models, self.elapsed_time_init)

#Store the outputs
self.y_prev = self.get_connection_outputs(initialize = True).copy()
self.set_last_y(self.y_prev)

def initialize_result_objects(self, opts):
if (opts["result_handling"] == "custom") and (not isinstance(opts["result_handler"], dict)):
raise FMUException("'result_handler' option must be a dictionary for 'result_handling' = 'custom'.")
Expand Down Expand Up @@ -1666,8 +1662,13 @@ cdef class Master:
time_stop = timer()
print('Elapsed initialization time: ' + str(time_stop-time_start) + ' seconds.')

# Get outputs and update previous values
self.y_prev = self.get_connection_outputs(initialize = True).copy()
self.set_last_y(self.y_prev)
self.y_discrete_prev = self.get_connection_outputs_discrete(initialize = True).copy()

#Store the inputs
self.set_last_us(self.L.dot(self.get_connection_outputs()))
self.set_last_us(self.L.dot(self.y_prev))

#Copy FMU address (used when evaluating in parallel)
self.copy_fmu_addresses()
Expand Down
33 changes: 33 additions & 0 deletions tests/test_fmi_master.py
Original file line number Diff line number Diff line change
Expand Up @@ -843,3 +843,36 @@ def compute_global_D(self):
"Actual values may no longer be sensible."
with pytest.warns(UserWarning, match = re.escape(msg)):
master.simulate(t_start, t_final, options = opts)

def test_with_manual_initialization(self):
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]
connections = [
(fmu1, "Float64_continuous_output", fmu2, "Float64_continuous_input"),
(fmu2, "Float64_continuous_output", fmu3, "Float64_continuous_input"),

(fmu1, "Float64_discrete_output", fmu2, "Float64_discrete_input"),
(fmu2, "Float64_discrete_output", fmu3, "Float64_discrete_input"),
]
master = Master(models, connections)
opts = master.simulate_options()
opts["step_size"] = 0.1
opts["step_size_downsampling_factor"] = {fmu1: 5, fmu2: 2, fmu3: 1}

fmu1.initialize()
fmu2.initialize()
fmu3.initialize()
opts["initialize"] = False

res = master.simulate(options = opts)

assert set(res[0]["Float64_continuous_output"].tolist()) == set([0.])
assert set(res[1]["Float64_continuous_output"].tolist()) == set([0.])
assert set(res[2]["Float64_continuous_output"].tolist()) == set([0.])

assert set(res[0]["Float64_discrete_output"].tolist()) == set([0.])
assert set(res[1]["Float64_discrete_output"].tolist()) == set([0.])
assert set(res[2]["Float64_discrete_output"].tolist()) == set([0.])
Loading