Skip to content
Draft
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
4 changes: 4 additions & 0 deletions brian2/core/magic.py
Original file line number Diff line number Diff line change
Expand Up @@ -489,3 +489,7 @@ def start_scope():
included by the magic functions such as `run`.
"""
BrianObject._scope_current_key += 1

# Run garbage collection here to destroy stale objects from previous runs
# preventing them from squatting on auto-generated names in the InstanceFollower
gc.collect()
3 changes: 2 additions & 1 deletion brian2/core/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,14 +543,15 @@ def add(self, *objs):
"""
for obj in objs:
if isinstance(obj, BrianObject):
if obj._network is not None:
if obj._network is not None and obj._network != self.id:
raise RuntimeError(
f"{obj.name} has already been simulated, cannot "
"add it to the network. If you were "
"trying to remove and add an object to "
"temporarily stop it from being run, "
"set its active flag to False instead."
)
obj._network = self.id
self.objects.add(obj)
else:
# allow adding values from dictionaries
Expand Down
27 changes: 27 additions & 0 deletions brian2/tests/test_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -1922,6 +1922,33 @@ def test_negative_duration_in_net_run():
net.run(-1 * second)


@pytest.mark.codegen_independent
def test_network_restore_loop():
# Issue 1814: Verify that running and restoring networks in a loop
# does not raise KeyError due to auto-generated clocks leaking iteratively
filename = tempfile.mktemp(suffix="state", prefix="brian_test")
try:
start_scope()
G = NeuronGroup(10, "v:1", name="G")
G.run_regularly("v += 0.1", dt=1 * ms)
net = Network(collect())
net.run(1 * ms)
net.store(filename=filename)

for i in range(2):
start_scope()
G = NeuronGroup(10, "v:1", name="G")
G.run_regularly("v += 0.1", dt=1 * ms)
net2 = Network(collect())
net2.restore(filename=filename)
net2.run(1 * ms)
finally:
try:
os.remove(filename)
except OSError:
pass


if __name__ == "__main__":
BrianLogger.log_level_warn()
for t in [
Expand Down
Loading