Skip to content

Fix KeyError when solving after insert_node (non-contiguous element ids) (#308)#443

Merged
brookshsmith merged 1 commit into
anastruct:masterfrom
gaoflow:fix/308-insert-node-noncontiguous-element-ids
Jun 2, 2026
Merged

Fix KeyError when solving after insert_node (non-contiguous element ids) (#308)#443
brookshsmith merged 1 commit into
anastruct:masterfrom
gaoflow:fix/308-insert-node-noncontiguous-element-ids

Conversation

@gaoflow
Copy link
Copy Markdown
Contributor

@gaoflow gaoflow commented Jun 1, 2026

Summary

Fixes #308.

insert_node() splits an element by appending two new elements and then removing the original via remove_element(). This leaves system.element_map with non-contiguous keys — e.g. after inserting a node into element 2 of a 2-element model, the map holds {1, 3, 4}.

assemble_system_matrix iterated positionally:

for i in range(len(system.element_map)):
    element = system.element_map[i + 1]

which assumes the ids are exactly 1..N. With a gap, element_map[2] no longer exists and validation/solving raises KeyError: 2.

This positional assumption is isolated to this one loop — everywhere else in the codebase indexes element_map by an actual element id, and add_element assigns ids from a monotonic counter that is never reused.

Fix

Iterate over the elements directly:

for element in system.element_map.values():

Assembly is an order-independent accumulation into the global system matrix indexed by node id, so this is identical to the old behaviour for the contiguous case and correct when ids have gaps.

Reproduction (raises on master)

from anastruct import SystemElements
s = SystemElements(EA=15000, EI=5000, mesh=101)
s.add_element(location=[[0, 0], [10, 4]])
s.add_element(location=[[10, 4], [10, 0]])
s.add_support_hinged(node_id=1)
s.add_support_hinged(node_id=3)
s.q_load(q=5, element_id=1, direction='element')
s.point_load(node_id=2, Fx=4, Fy=0)
s.insert_node(element_id=2, factor=0.25)
s.point_load(node_id=4, Fx=8, Fy=0)
s.solve()   # KeyError: 2  (assembly.py)

Verification

  • New end-to-end test context_insert_node_then_solve reproduces the issue and additionally asserts the solved result is numerically identical to the equivalent model built with the extra node defined up front (same displacements at every shared node). It raises KeyError: 2 on master and passes with this change.
  • Full test suite passes (the 6 pre-existing test_plotter failures — 'Plotter' object has no attribute 'plot_structure' — are unrelated to this change and fail identically on master).
  • black and mypy clean on the changed files.

Note

This supersedes #309 (from the issue reporter @thisisapple), which proposed the same element_map.values() idea but contains a syntax error (for keyword dropped) and no test. Credit to them for the original diagnosis.

insert_node() removes the split element and appends two new ones, leaving
element_map with non-contiguous keys (e.g. {1, 3, 4}). assemble_system_matrix
iterated 'for i in range(len(element_map)): element_map[i + 1]', which assumed
ids 1..N and raised KeyError during validation/solve. Iterate over
element_map.values() instead; assembly is an order-independent accumulation
into the system matrix indexed by node id, so this is equivalent for the
contiguous case and correct when ids have gaps.

Fixes anastruct#308
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

Thank you so much for contributing to the open-source anaStruct project! Your contribution will help thousands of engineers work more efficiently and accuractely.

Now that you've created your first pull request here, please don't go away; take a look at the bottom of this page for the automated checks that should already be running. If they pass, great! If not, please click on 'Details' and see if you can fix the problem they've identified. Keep in mind that this repository uses the black autoformatter, pylint linter, and mypy type-checking; the most common problems can be fixed by making sure you've installed and run those systems. A maintainer should be along shortly to review your pull request and help get it added to anaStruct!

@brookshsmith brookshsmith self-requested a review June 2, 2026 10:23
Copy link
Copy Markdown
Collaborator

@brookshsmith brookshsmith left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @gaoflow for your PR here as well! Again, a simple but needed fix and you've added a good test too. Merged.

@brookshsmith brookshsmith merged commit 2484aa2 into anastruct:master Jun 2, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inserting a node to existing element causes a key error because that element is deleted.

2 participants