Skip to content

Commit 3ffa884

Browse files
authored
Merge pull request #217 from ritchie46/removeElementOrphanedNodes
Remove orphaned nodes in remove_element()
2 parents b565110 + 276c01a commit 3ffa884

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

anastruct/fem/system.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,12 +477,20 @@ def remove_element(self, element_id: int) -> None:
477477
element_id (int): ID of the element to remove
478478
"""
479479
element = self.element_map[element_id]
480-
for node_id in (element.node_id1, element.node_id2):
480+
node_id1 = element.node_id1
481+
node_id2 = element.node_id2
482+
483+
# Remove element object itself from node maps
484+
for node_id in (node_id1, node_id2):
481485
self.node_element_map[node_id].remove(element)
482486
if len(self.node_element_map[node_id]) == 0:
483487
self.node_element_map.pop(node_id)
484488
self.node_map[node_id].elements.pop(element_id)
489+
# Check if node is now orphaned, and remove it and its loads if so
490+
if len(self.node_map[node_id].elements) == 0:
491+
system_components.util.remove_node_id(self, node_id)
485492

493+
# Remove element_id
486494
self.element_map.pop(element_id)
487495
if element_id in self.loads_q:
488496
self.loads_q.pop(element_id)

anastruct/fem/system_components/util.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,56 @@ def append_node_id(
7878
system.node_map[node_id2] = Node(node_id2, vertex=point_2)
7979

8080

81+
def remove_node_id(
82+
system: "SystemElements",
83+
node_id: int,
84+
) -> None:
85+
"""Remove the node id from the system
86+
87+
Note that this function does NOT check if the node is still used in the system. It is
88+
intended to be used as a helper function to `remove_element()` and others, not to be
89+
used directly by users.
90+
91+
Args:
92+
system (SystemElements): System in which the node is located
93+
node_id (int): Node id of the node
94+
"""
95+
node = system.node_map[node_id]
96+
system._vertices.pop(system.node_map[node_id].vertex)
97+
system.node_map.pop(node_id)
98+
if node_id in system.loads_point:
99+
system.loads_point.pop(node_id)
100+
if node_id in system.loads_moment:
101+
system.loads_moment.pop(node_id)
102+
if node in system.supports_fixed:
103+
system.supports_fixed.remove(node)
104+
if node in system.supports_hinged:
105+
system.supports_hinged.remove(node)
106+
if node in system.supports_rotational:
107+
system.supports_rotational.remove(node)
108+
if node in system.internal_hinges:
109+
system.internal_hinges.remove(node)
110+
if node in system.supports_roll:
111+
ind = system.supports_roll.index(node)
112+
system.supports_roll.remove(node)
113+
system.supports_roll_direction.pop(ind)
114+
system.supports_roll_rotate.pop(ind)
115+
if node_id in system.inclined_roll:
116+
system.inclined_roll.pop(node_id)
117+
if node in [item[0] for item in system.supports_spring_x]:
118+
ind = [item[0] for item in system.supports_spring_x].index(node)
119+
system.supports_spring_x.pop(ind)
120+
if node in [item[0] for item in system.supports_spring_y]:
121+
ind = [item[0] for item in system.supports_spring_y].index(node)
122+
system.supports_spring_y.pop(ind)
123+
if node in [item[0] for item in system.supports_spring_z]:
124+
ind = [item[0] for item in system.supports_spring_z].index(node)
125+
system.supports_spring_z.pop(ind)
126+
if node_id in [item[0] for item in system.supports_spring_args]:
127+
ind = [item[0] for item in system.supports_spring_args].index(node_id)
128+
system.supports_spring_args.pop(ind)
129+
130+
81131
def det_vertices(
82132
system: "SystemElements",
83133
location_list: Union[

tests/test_e2e.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,3 +1016,31 @@ def it_results_in_correct_deflections():
10161016
assert system.get_node_results_system(1)["uy"] == approx(
10171017
-w * l**4 / (8 * EI)
10181018
)
1019+
1020+
def context_remove_element():
1021+
@pspec_context("Removing an element from a propped beam")
1022+
def describe():
1023+
pass
1024+
1025+
system = SystemElements()
1026+
system.add_element([[0, 0], [10, 0]])
1027+
system.add_element([[10, 0], [15, 0]])
1028+
system.add_support_hinged(1)
1029+
system.add_support_hinged(2)
1030+
system.q_load(q=-1, element_id=1)
1031+
system.q_load(q=-1, element_id=2)
1032+
system.point_load(node_id=3, Fy=-10)
1033+
system.remove_element(2)
1034+
system.solve()
1035+
1036+
def it_removes_element():
1037+
assert len(system.element_map) == 1
1038+
assert not (2 in system.loads_q)
1039+
1040+
def it_removes_orphaned_node():
1041+
assert len(system.node_map) == 2
1042+
assert not (3 in system.loads_point)
1043+
1044+
def it_results_in_correct_reactions():
1045+
assert system.get_node_results_system(1)["Fy"] == approx(-5)
1046+
assert system.get_node_results_system(2)["Fy"] == approx(-5)

0 commit comments

Comments
 (0)