Skip to content

Commit c0c49ff

Browse files
committed
add plots of reactions
1 parent df3cd9e commit c0c49ff

File tree

3 files changed

+165
-0
lines changed

3 files changed

+165
-0
lines changed

pystran/plots.py

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,3 +1243,144 @@ def show(m):
12431243
ax.set_ylabel("Y")
12441244
ax.set_zlabel("Z")
12451245
plt.show()
1246+
1247+
1248+
def plot_reaction_forces(m, scale=0.0):
1249+
"""
1250+
Plot the reaction forces at the joints.
1251+
1252+
Parameters
1253+
----------
1254+
m
1255+
Model dictionary.
1256+
scale
1257+
Optional: scale factor for the arrows. Forces are rendered with single
1258+
arrows. Default is 0.0, which means compute this internally.
1259+
1260+
"""
1261+
ax = plt.gca()
1262+
dim = m["dim"]
1263+
cd = characteristic_dimension(m)
1264+
1265+
def fun(j):
1266+
if "reactions" in j and j["reactions"]:
1267+
return [v for (d, v) in j["reactions"].items() if d < dim]
1268+
else:
1269+
return [0]
1270+
1271+
if scale == 0.0:
1272+
maxmag = _largest_mag_at_joints(m, fun)
1273+
if maxmag != 0:
1274+
scale = cd / 2 / maxmag
1275+
for j in m["joints"].values():
1276+
if "reactions" in j and j["reactions"]:
1277+
for d in j["reactions"].keys():
1278+
F = zeros((dim,))
1279+
if d < dim:
1280+
F[d] = j["reactions"][d]
1281+
if norm(F) > 0:
1282+
if dim == 2:
1283+
x, y = j["coordinates"]
1284+
u, v = F
1285+
ax.arrow(
1286+
x,
1287+
y,
1288+
scale * u,
1289+
scale * v,
1290+
head_width=cd / 20,
1291+
head_length=cd / 20,
1292+
color="green",
1293+
)
1294+
else:
1295+
x, y, z = j["coordinates"]
1296+
u, v, w = F
1297+
ax.arrow3D(
1298+
x,
1299+
y,
1300+
z,
1301+
scale * u,
1302+
scale * v,
1303+
scale * w,
1304+
mutation_scale=20,
1305+
arrowstyle="-|>",
1306+
color="green",
1307+
)
1308+
return ax
1309+
1310+
1311+
def plot_reaction_moments(m, scale=0.0, radius=0.0):
1312+
"""
1313+
Plot the reaction moments at the joints.
1314+
1315+
Parameters
1316+
----------
1317+
m
1318+
Model dictionary.
1319+
scale
1320+
Optional: scale factor for the arrows. Moments are rendered with double
1321+
arrows. Default is 0.0, which means compute this internally.
1322+
radius
1323+
Radius of the circle to represent the moment (2D only). Default is 0.0,
1324+
which means compute this internally.
1325+
"""
1326+
ax = plt.gca()
1327+
dim = m["dim"]
1328+
ndpn = ndof_per_joint(m)
1329+
cd = characteristic_dimension(m)
1330+
1331+
def fun(j):
1332+
if "reactions" in j and j["reactions"]:
1333+
return [v for (d, v) in j["reactions"].items() if d >= dim]
1334+
else:
1335+
return [0]
1336+
1337+
if scale == 0.0:
1338+
maxmag = _largest_mag_at_joints(m, fun)
1339+
if maxmag != 0:
1340+
scale = cd / 2 / maxmag
1341+
if radius <= 0.0:
1342+
radius = cd / 10
1343+
for j in m["joints"].values():
1344+
if "reactions" in j and j["reactions"]:
1345+
for d in j["reactions"].keys():
1346+
M = zeros((ndpn - dim,))
1347+
if d >= dim:
1348+
M[d - dim] = j["reactions"][d]
1349+
if norm(M) > 0:
1350+
if dim == 2:
1351+
x, y = j["coordinates"]
1352+
if M > 0:
1353+
st = -110
1354+
dl = 210
1355+
sense = +1
1356+
else:
1357+
st = 80
1358+
dl = 210
1359+
sense = -1
1360+
_drawcirc(ax, radius, x, y, st, dl, sense, color_="green")
1361+
else:
1362+
x, y, z = j["coordinates"]
1363+
u, v, w = M
1364+
ax.arrow3D(
1365+
x,
1366+
y,
1367+
z,
1368+
scale * u,
1369+
scale * v,
1370+
scale * w,
1371+
mutation_scale=20,
1372+
arrowstyle="-|>",
1373+
color="green",
1374+
)
1375+
ax.arrow3D(
1376+
x,
1377+
y,
1378+
z,
1379+
scale * 0.9 * u,
1380+
scale * 0.9 * v,
1381+
scale * 0.9 * w,
1382+
mutation_scale=20,
1383+
arrowstyle="-|>",
1384+
color="green",
1385+
)
1386+
return ax

tutorials/02_continuous_beam_2_spans_consist_tut.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,11 @@
126126
ax = plots.plot_shear_forces(m)
127127
ax.set_title("Shear forces")
128128
plots.show(m)
129+
130+
# The reaction forces can be plotted after the reactions have been computed.
131+
model.statics_reactions(m)
132+
plots.setup(m)
133+
plots.plot_members(m)
134+
ax = plots.plot_reaction_forces(m)
135+
ax.set_title("Reaction forces")
136+
plots.show(m)

tutorials/03_weaver_1_tut.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,3 +281,19 @@
281281
ax.set_title("Axial forces")
282282
ax.view_init(elev=137, azim=-67, roll=30)
283283
plots.show(m)
284+
285+
286+
# We have computed the reactions above. Now we can visualize them.
287+
ax = plots.setup(m)
288+
plots.plot_members(m)
289+
ax = plots.plot_reaction_forces(m)
290+
ax.set_title("Reaction forces")
291+
ax.view_init(elev=137, azim=-67, roll=30)
292+
plots.show(m)
293+
294+
ax = plots.setup(m)
295+
plots.plot_members(m)
296+
ax = plots.plot_reaction_moments(m)
297+
ax.set_title("Reaction moments")
298+
ax.view_init(elev=137, azim=-67, roll=30)
299+
plots.show(m)

0 commit comments

Comments
 (0)