SymPy 1.13 中文文档(四十二)
使用奇异函数解决梁弯曲问题
原文链接:
docs.sympy.org/latest/modules/physics/continuum_mechanics/beam_problems.html
若要使本文档更易读,请启用漂亮的打印格式:
>>> from sympy import *
>>> x, y, z = symbols('x y z')
>>> init_printing(use_unicode=True)
梁
平面梁是一种通过抗拒内部剪切力和弯矩来承受负载的结构元件。梁的特性由其长度、约束条件、横截面二阶矩和弹性模量确定。在 SymPy 中,通过指定以下属性来构造 2D 梁对象:
-
长度
-
弹性模量
-
截面二阶矩
-
变量:代表沿梁长度的位置的符号。默认情况下,设置为
Symbol(x)。 -
边界条件
-
bc_slope:斜率的边界条件。
-
bc_deflection:挠度的边界条件。
-
-
载荷分布
一旦以上内容被指定,以下方法用于计算关于加载梁的有用信息:
-
solve_for_reaction_loads() -
shear_force() -
bending_moment() -
slope()
示例
下面是二维梁弯曲问题的各种示例。
示例 1
一根 9 米长的悬臂梁,在固定端上施加一个 8 kN/m 的常数分布载荷,距离固定端 5 米的范围内。从固定端 5 米处施加一个逆时针力矩为 50 kN·m。最后,在梁的自由端施加一个 12 kN 的向下点载荷。
y
^
|
\\\\|
\\\\| 8 kN/m
\\\\|_________________
\\\\|| | | | | | | | | 12 kN
\\\\|V V V V V V V V V |
\\\\|________________|_______________V
\\\\| | |
\\\\o - - - - - - - -⭯ 50 kN-m - - - | - - -> x
\\\\|________________|_______________|
\\\\| :
\\\\|----------------|---------------|
5.0 m 4.0 m
注意
用户可以自由选择其符号约定。在这种情况下,向下的力和逆时针弯矩被视为正。
必须使用长度、弹性模量和二阶矩初始化梁。这些量可以是符号或数字。
>>> from sympy.physics.continuum_mechanics.beam import Beam
>>> E, I = symbols('E, I')
>>> b = Beam(9, E, I)
使用apply_load()方法对梁施加三个载荷。此方法支持点力、点力矩和任意阶数的多项式分布载荷,即(c, cx, cx², cx³, \ldots)。
12 kN 点载荷朝负方向作用在距离为 9 米处,多项式阶数指定为-1:
>>> b.apply_load(12, 9, -1)
然后可以使用load属性来访问奇异函数形式的加载函数:
>>> b.load
-1
12⋅<x - 9>
同样地,正弯矩可以使用多项式阶数-2 施加:
>>> b.apply_load(50, 5, -2)
分布载荷的阶数为 0,跨越 x=0 到 x=5:
>>> b.apply_load(8, 0, 0, end=5)
固定端施加两个边界条件:1)无竖向挠度,2)无转动。这些条件通过追加 x 值元组和相应的挠度或斜率值来指定:
>>> b.bc_deflection.append((0, 0))
>>> b.bc_slope.append((0, 0))
这些边界条件引入了需要施加到梁上以保持静力平衡的未知反作用力和弯矩:
>>> R, M = symbols('R, M')
>>> b.apply_load(R, 0, -1)
>>> b.apply_load(M, 0, -2)
>>> b.load
-2 -1 0 -2 0 -1
M⋅<x> + R⋅<x> + 8⋅<x> + 50⋅<x - 5> - 8⋅<x - 5> + 12⋅<x - 9>
这两个变量可以用施加载荷和最终加载的术语来求解:
>>> b.solve_for_reaction_loads(R, M)
>>> b.reaction_loads
{M: 158, R: -52}
>>> b.load
-2 -1 0 -2 0 -1
158⋅<x> - 52⋅<x> + 8⋅<x> + 50⋅<x - 5> - 8⋅<x - 5> + 12⋅<x - 9>
此时,梁已完全定义,并计算了内部剪切力和弯矩。
>>> b.shear_force()
-1 0 1 -1 1 0
- 158⋅<x> + 52⋅<x> - 8⋅<x> - 50⋅<x - 5> + 8⋅<x - 5> - 12⋅<x - 9>
>>> b.bending_moment()
0 1 2 0 2 1
- 158⋅<x> + 52⋅<x> - 4⋅<x> - 50⋅<x - 5> + 4⋅<x - 5> - 12⋅<x - 9>
这些可以通过调用各自的绘图方法来可视化:
>>> b.plot_shear_force()
>>> b.plot_bending_moment()
(png, hires.png, pdf)
(png, hires.png, pdf)
梁在载荷作用下会变形,斜率和挠度可以通过以下方式确定:
>>> b.slope()
⎛ 3 3 ⎞
⎜ 1 2 4⋅<x> 1 4⋅<x - 5> 2⎟
-⎜- 158⋅<x> + 26⋅<x> - ────── - 50⋅<x - 5> + ────────── - 6⋅<x - 9> ⎟
⎝ 3 3 ⎠
─────────────────────────────────────────────────────────────────────────
E⋅I
>>> b.deflection()
⎛ 3 4 4 ⎞
⎜ 2 26⋅<x> <x> 2 <x - 5> 3⎟
-⎜- 79⋅<x> + ─────── - ──── - 25⋅<x - 5> + ──────── - 2⋅<x - 9> ⎟
⎝ 3 3 3 ⎠
────────────────────────────────────────────────────────────────────
E⋅I
梁的斜率和挠度可以绘制,只要弹性模量和惯性矩提供了数值:
>>> b.plot_slope(subs={E: 20E9, I: 3.25E-6})
>>> b.plot_deflection(subs={E: 20E9, I: 3.25E-6})
(png, hires.png, pdf)
(png, hires.png, pdf)
所有图表均可在一个图中显示:
>>> b.plot_loading_results(subs={E: 20E9, I: 3.25E-6})
(png, hires.png, pdf)
示例 2
一根长度为 30 米的梁。梁末端施加 120 Nm 的逆时针力矩。从梁起点处施加 8 N 的点载荷。梁下有两个简支。一个在末端,另一个在距离起点 10 米处。两个支点处的挠度被限制。
|| 8 N ⭯ 120 Nm
\/______________________________________________|
|_______________________________________________|
/\ /\
|------------|---------------------------------|
10 m 20 m
注意
使用向下力和逆时针力矩为正的符号约定。
>>> from sympy.physics.continuum_mechanics.beam import Beam
>>> from sympy import symbols
>>> E, I = symbols('E, I')
>>> R1, R2 = symbols('R1, R2')
>>> b = Beam(30, E, I)
>>> b.apply_load(8, 0, -1)
>>> b.apply_load(R1, 10, -1)
>>> b.apply_load(R2, 30, -1)
>>> b.apply_load(120, 30, -2)
>>> b.bc_deflection.append((10, 0))
>>> b.bc_deflection.append((30, 0))
>>> b.solve_for_reaction_loads(R1, R2)
>>> b.reaction_loads
{R₁: -18, R₂: 10}
>>> b.load
-1 -1 -2 -1
8⋅<x> - 18⋅<x - 10> + 120⋅<x - 30> + 10⋅<x - 30>
>>> b.shear_force()
0 0 -1 0
- 8⋅<x> + 18⋅<x - 10> - 120⋅<x - 30> - 10⋅<x - 30>
>>> b.bending_moment()
1 1 0 1
- 8⋅<x> + 18⋅<x - 10> - 120⋅<x - 30> - 10⋅<x - 30>
>>> b.slope()
2 2 1 2 1600
4⋅<x> - 9⋅<x - 10> + 120⋅<x - 30> + 5⋅<x - 30> - ────
3
─────────────────────────────────────────────────────────
E⋅I
>>> b.deflection()
3 3
1600⋅x 4⋅<x> 3 2 5⋅<x - 30>
- ────── + ────── - 3⋅<x - 10> + 60⋅<x - 30> + ─────────── + 4000
3 3 3
───────────────────────────────────────────────────────────────────
E⋅I
示例 3
一根长度为 6 米的梁,起始处有滚动支撑,末端有铰接支撑。梁的中点施加逆时针力矩 1.5 kN·m。从中点到梁末端施加 3 kN/m 的均布载荷和 1 kN/m/m 的坡载荷。
ramp load = 1 KN/m/m
constant load = 3 KN/m
|------------------------|
⭯ 1.5 KN-m
______________________|________________________
|_______________________________________________|
o | /\
|----------------------|-----------------------|
3.0 m 3.0 m
注意
使用向下力和逆时针力矩为正的符号约定。
>>> from sympy.physics.continuum_mechanics.beam import Beam
>>> from sympy import symbols, plot, S
>>> E, I = symbols('E, I')
>>> R1, R2 = symbols('R1, R2')
>>> b = Beam(6, E, I)
>>> b.apply_load(R1, 0, -1)
>>> b.apply_load(-S(3)/2, 3, -2)
>>> b.apply_load(3, 3, 0)
>>> b.apply_load(1, 3, 1)
>>> b.apply_load(R2, 6, -1)
>>> b.bc_deflection.append((0, 0))
>>> b.bc_deflection.append((6, 0))
>>> b.solve_for_reaction_loads(R1, R2)
>>> b.reaction_loads
{R₁: -11/4, R₂: -43/4}
>>> b.load
-1 -2 -1
11⋅<x> 3⋅<x - 3> 0 1 43⋅<x - 6>
- ──────── - ─────────── + 3⋅<x - 3> + <x - 3> - ────────────
4 2 4
>>> plot(b.load)
(png, hires.png, pdf)
>>> b.shear_force()
0 -1 2 0
11⋅<x> 3⋅<x - 3> 1 <x - 3> 43⋅<x - 6>
─────── + ─────────── - 3⋅<x - 3> - ──────── + ───────────
4 2 2 4
>>> b.bending_moment()
1 0 2 3 1
11⋅<x> 3⋅<x - 3> 3⋅<x - 3> <x - 3> 43⋅<x - 6>
─────── + ────────── - ────────── - ──────── + ───────────
4 2 2 6 4
>>> b.slope()
2 1 3 4 2
11⋅<x> 3⋅<x - 3> <x - 3> <x - 3> 43⋅<x - 6> 78
- ─────── - ────────── + ──────── + ──────── - ─────────── + ──
8 2 2 24 8 5
───────────────────────────────────────────────────────────────
E⋅I
>>> b.deflection()
3 2 4 5 3
78⋅x 11⋅<x> 3⋅<x - 3> <x - 3> <x - 3> 43⋅<x - 6>
──── - ─────── - ────────── + ──────── + ──────── - ───────────
5 24 4 8 120 24
───────────────────────────────────────────────────────────────
E⋅I
例 4
一个长度为 8 米的悬臂梁,在距离起始点 1 米处铰接支撑,并在距离另一端 1 米处的辊子支持下。从起始点到距离其 2 米处的区间上承受了 10 KN/m 的均布恒载。在距离起始点分别为 5 米和 7.5 米处施加了两个点载荷,大小分别为 20KN 和 8KN。
---> x
|
v y
10 KN/m
_____________ 20 KN 8 KN
| | | | | | | | |
V V V V V V V V V
_______________________________________________
|_______________________________________________|
/\ O
|-----|------|-----------------|----------|--|--|
1m 1m 3m 2m .5m .5m
>>> from sympy.physics.continuum_mechanics.beam import Beam
>>> from sympy import symbols
>>> E,I,M,V = symbols('E I M V')
>>> b = Beam(8, E, I)
>>> E,I,R1,R2 = symbols('E I R1 R2')
>>> b.apply_load(R1, 1, -1)
>>> b.apply_load(R2, 7, -1)
>>> b.apply_load(10, 0, 0, end=2)
>>> b.apply_load(20, 5, -1)
>>> b.apply_load(8, 7.5, -1)
>>> b.solve_for_reaction_loads(R1, R2)
>>> b.reaction_loads
{R₁: -26, R₂: -22}
>>> b.load
0 -1 0 -1 -1 -1
10⋅<x> - 26⋅<x - 1> - 10⋅<x - 2> + 20⋅<x - 5> - 22⋅<x - 7> + 8⋅<x - 7.5>
>>> b.shear_force()
1 0 1 0 0 0
- 10⋅<x> + 26⋅<x - 1> + 10⋅<x - 2> - 20⋅<x - 5> + 22⋅<x - 7> - 8⋅<x - 7.5>
>>> b.bending_moment()
2 1 2 1 1 1
- 5⋅<x> + 26⋅<x - 1> + 5⋅<x - 2> - 20⋅<x - 5> + 22⋅<x - 7> - 8⋅<x - 7.5>
>>> b.bc_deflection = [(1, 0), (7, 0)]
>>> b.slope()
3 3
5⋅<x> 2 5⋅<x - 2> 2 2 2 679
────── - 13⋅<x - 1> - ────────── + 10⋅<x - 5> - 11⋅<x - 7> + 4⋅<x - 7.5> + ───
3 3 24
──────────────────────────────────────────────────────────────────────────────────
E⋅I
>>> b.deflection()
4 3 4 3 3 3
679⋅x 5⋅<x> 13⋅<x - 1> 5⋅<x - 2> 10⋅<x - 5> 11⋅<x - 7> 4⋅<x - 7.5> 689
───── + ────── - ─────────── - ────────── + ─────────── - ─────────── + ──────────── - ───
24 12 3 12 3 3 3 24
──────────────────────────────────────────────────────────────────────────────────────────
E⋅I
例 5
一个长度为 6 米的悬臂梁,在起始点到距离其 2 米处的区间上承受均布的恒定向下载荷,大小为 4.0 KN/m。从中点到梁的末端施加了 1 kN/m/m 的坡道载荷。同时,在起始点距离 4 米处也施加了大小为 12KN 的点载荷。
---> x .
| . |
v y 12 KN . | |
| . | | |
V . | | | |
\\\\| 4 KN/m . | | | | |
\\\\|___________ . 1 KN/m/m| |
\\\\|| | | | | | . V V V V V V V
\\\\|V V V V V V |---------------|
\\\\|________________________________
\\\\|________________________________|
\\\\| : : :
\\\\|----------|-----|----|----------|
2.0 m 1m 1m 2.0 m
>>> from sympy.physics.continuum_mechanics.beam import Beam
>>> from sympy import symbols
>>> E,I,M,V = symbols('E I M V')
>>> b = Beam(6, E, I)
>>> b.apply_load(V, 0, -1)
>>> b.apply_load(M, 0, -2)
>>> b.apply_load(4, 0, 0, end=2)
>>> b.apply_load(12, 4, -1)
>>> b.apply_load(1, 3, 1, end=6)
>>> b.solve_for_reaction_loads(V, M)
>>> b.reaction_loads
{M: 157/2, V: -49/2}
>>> b.load
-2 -1
157⋅<x> 49⋅<x> 0 0 1 -1 0 1
───────── - ──────── + 4⋅<x> - 4⋅<x - 2> + <x - 3> + 12⋅<x - 4> - 3⋅<x - 6> - <x - 6>
2 2
>>> b.shear_force()
-1 0 2 2
157⋅<x> 49⋅<x> 1 1 <x - 3> 0 1 <x - 6>
- ───────── + ─────── - 4⋅<x> + 4⋅<x - 2> - ──────── - 12⋅<x - 4> + 3⋅<x - 6> + ────────
2 2 2 2
>>> b.bending_moment()
0 1 3 2 3
157⋅<x> 49⋅<x> 2 2 <x - 3> 1 3⋅<x - 6> <x - 6>
- ──────── + ─────── - 2⋅<x> + 2⋅<x - 2> - ──────── - 12⋅<x - 4> + ────────── + ────────
2 2 6 2 6
>>> b.bc_deflection = [(0, 0)]
>>> b.bc_slope = [(0, 0)]
>>> b.slope()
⎛ 1 2 3 3 4 3 4⎞
⎜ 157⋅<x> 49⋅<x> 2⋅<x> 2⋅<x - 2> <x - 3> 2 <x - 6> <x - 6> ⎟
-⎜- ──────── + ─────── - ────── + ────────── - ──────── - 6⋅<x - 4> + ──────── + ────────⎟
⎝ 2 4 3 3 24 2 24 ⎠
────────────────────────────────────────────────────────────────────────────────────────────
E⋅I
>>> b.deflection()
⎛ 2 3 4 4 5 4 5⎞
⎜ 157⋅<x> 49⋅<x> <x> <x - 2> <x - 3> 3 <x - 6> <x - 6> ⎟
-⎜- ──────── + ─────── - ──── + ──────── - ──────── - 2⋅<x - 4> + ──────── + ────────⎟
⎝ 4 12 6 6 120 8 120 ⎠
────────────────────────────────────────────────────────────────────────────────────────
E⋅I
例 6
一个长度为 11 米的悬臂梁,在距离起始点 2 米处到距离其 6 米处的区间上承受了 2 KN/m 的均布恒载。它在起始点铰接支撑,并在距离其 8 米处的辊子上支撑。此外,还施加了一个 5 KN-m 的逆时针力矩在悬臂端。
2 KN/m ---> x
_________________ |
| | | | | | | | | v y
V V V V V V V V V ⭯ 5 KN-m
____________________________________________________|
O____________________________________________________|
/ \ /\
|--------|----------------|----------|---------------|
2m 4m 2m 3m
>>> from sympy.physics.continuum_mechanics.beam import Beam
>>> from sympy import symbols
>>> R1, R2 = symbols('R1, R2')
>>> E, I = symbols('E, I')
>>> b = Beam(11, E, I)
>>> b.apply_load(R1, 0, -1)
>>> b.apply_load(2, 2, 0, end=6)
>>> b.apply_load(R2, 8, -1)
>>> b.apply_load(5, 11, -2)
>>> b.solve_for_reaction_loads(R1, R2)
>>> b.reaction_loads
{R₁: -37/8, R₂: -27/8}
>>> b.load
-1 -1
37⋅<x> 0 0 27⋅<x - 8> -2
- ──────── + 2⋅<x - 2> - 2⋅<x - 6> - ──────────── + 5⋅<x - 11>
8 8
>>> b.shear_force()
0 0
37⋅<x> 1 1 27⋅<x - 8> -1
─────── - 2⋅<x - 2> + 2⋅<x - 6> + ─────────── - 5⋅<x - 11>
8 8
>>> b.bending_moment()
1 1
37⋅<x> 2 2 27⋅<x - 8> 0
─────── - <x - 2> + <x - 6> + ─────────── - 5⋅<x - 11>
8 8
>>> b.bc_deflection = [(0, 0), (8, 0)]
>>> b.slope()
2 3 3 2
37⋅<x> <x - 2> <x - 6> 27⋅<x - 8> 1
- ─────── + ──────── - ──────── - ─────────── + 5⋅<x - 11> + 36
16 3 3 16
────────────────────────────────────────────────────────────────
E⋅I
>>> b.deflection()
3 4 4 3 2
37⋅<x> <x - 2> <x - 6> 9⋅<x - 8> 5⋅<x - 11>
36⋅x - ─────── + ──────── - ──────── - ────────── + ───────────
48 12 12 16 2
───────────────────────────────────────────────────────────────
E⋅I
例 7
一个长度为 l 的两端固定的梁。在梁的中点向下施加大小为 F 的集中力。
^ y
|
---> x
\\\\| F |\\\\
\\\\| | |\\\\
\\\\| V |\\\\
\\\\|_____________________________________|\\\\
\\\\|_____________________________________|\\\\
\\\\| : |\\\\
\\\\| : |\\\\
\\\\|------------------|------------------|\\\\
l/2 l/2
>>> from sympy.physics.continuum_mechanics.beam import Beam
>>> from sympy import symbols
>>> E, I, F = symbols('E I F')
>>> l = symbols('l', positive=True)
>>> b = Beam(l, E, I)
>>> R1,R2 = symbols('R1 R2')
>>> M1, M2 = symbols('M1, M2')
>>> b.apply_load(R1, 0, -1)
>>> b.apply_load(M1, 0, -2)
>>> b.apply_load(R2, l, -1)
>>> b.apply_load(M2, l, -2)
>>> b.apply_load(-F, l/2, -1)
>>> b.bc_deflection = [(0, 0),(l, 0)]
>>> b.bc_slope = [(0, 0),(l, 0)]
>>> b.solve_for_reaction_loads(R1, R2, M1, M2)
>>> b.reaction_loads
⎧ -F⋅l F⋅l F F⎫
⎨M₁: ─────, M₂: ───, R₁: ─, R₂: ─⎬
⎩ 8 8 2 2⎭
>>> b.load
-2 -2 -1 -1 -1
F⋅l⋅<x> F⋅l⋅<-l + x> F⋅<x> l F⋅<-l + x>
- ───────── + ────────────── + ─────── - F⋅<- ─ + x> + ────────────
8 8 2 2 2
>>> b.shear_force()
-1 -1 0 0 0
F⋅l⋅<x> F⋅l⋅<-l + x> F⋅<x> l F⋅<-l + x>
───────── - ────────────── - ────── + F⋅<- ─ + x> - ───────────
8 8 2 2 2
>>> b.bending_moment()
0 0 1 1 1
F⋅l⋅<x> F⋅l⋅<-l + x> F⋅<x> l F⋅<-l + x>
──────── - ───────────── - ────── + F⋅<- ─ + x> - ───────────
8 8 2 2 2
>>> b.slope()
⎛ 2 ⎞
⎜ l ⎟
⎜ 1 1 2 F⋅<- ─ + x> 2⎟
⎜F⋅l⋅<x> F⋅l⋅<-l + x> F⋅<x> 2 F⋅<-l + x> ⎟
-⎜──────── - ───────────── - ────── + ──────────── - ───────────⎟
⎝ 8 8 4 2 4 ⎠
──────────────────────────────────────────────────────────────────
E⋅I
>>> b.deflection()
⎛ 3 ⎞
⎜ l ⎟
⎜ 2 2 3 F⋅<- ─ + x> 3⎟
⎜F⋅l⋅<x> F⋅l⋅<-l + x> F⋅<x> 2 F⋅<-l + x> ⎟
-⎜──────── - ───────────── - ────── + ──────────── - ───────────⎟
⎝ 16 16 12 6 12 ⎠
──────────────────────────────────────────────────────────────────
E⋅I
例 8
一个长度为 4*l 的梁,中间连接器为铰接。在起始点处固定支持,同时距离起始点为 l 和 4*l 处各有两个辊子支撑。在距离起始点为 3*l 处还施加了大小为 P 的集中点载荷。
---> x
\\\\| P |
\\\\| | v y
\\\\| V
\\\\|_____________________ _______________________
\\\\|_____________________O_______________________|
\\\\| /\ : /\
\\\\| oooo : oooo
\\\\|----------|-----------|----------|-----------|
l l l l
>>> from sympy.physics.continuum_mechanics.beam import Beam
>>> from sympy import symbols
>>> E, I = symbols('E I')
>>> l = symbols('l', positive=True)
>>> R1, M1, R2, R3, P = symbols('R1 M1 R2 R3 P')
>>> b1 = Beam(2*l, E, I)
>>> b2 = Beam(2*l, E, I)
>>> b = b1.join(b2, "hinge")
>>> b.apply_load(M1, 0, -2)
>>> b.apply_load(R1, 0, -1)
>>> b.apply_load(R2, l, -1)
>>> b.apply_load(R3, 4*l, -1)
>>> b.apply_load(P, 3*l, -1)
>>> b.bc_slope = [(0, 0)]
>>> b.bc_deflection = [(0, 0), (l, 0), (4*l, 0)]
>>> b.solve_for_reaction_loads(M1, R1, R2, R3)
>>> b.reaction_loads
⎧ -P⋅l 3⋅P -5⋅P -P ⎫
⎨M₁: ─────, R₁: ───, R₂: ─────, R₃: ───⎬
⎩ 4 4 4 2 ⎭
>>> b.load
-2 -1 -1 -1
P⋅l⋅<x> 3⋅P⋅<x> 5⋅P⋅<-l + x> -1 P⋅<-4⋅l + x>
- ───────── + ───────── - ────────────── + P⋅<-3⋅l + x> - ──────────────
4 4 4 2
>>> b.shear_force()
-1 0 0 0
P⋅l⋅<x> 3⋅P⋅<x> 5⋅P⋅<-l + x> 0 P⋅<-4⋅l + x>
───────── - ──────── + ───────────── - P⋅<-3⋅l + x> + ─────────────
4 4 4 2
>>> b.bending_moment()
0 1 1 1
P⋅l⋅<x> 3⋅P⋅<x> 5⋅P⋅<-l + x> 1 P⋅<-4⋅l + x>
──────── - ──────── + ───────────── - P⋅<-3⋅l + x> + ─────────────
4 4 4 2
>>> b.slope()
⎛ 2 2 2 2⎞ ⎛ 1 2 2 2⎞ ⎛ 1 2 2 2⎞
⎜5⋅P⋅l P⋅<-2⋅l + x> P⋅<-3⋅l + x> P⋅<-4⋅l + x> ⎟ 0 ⎜ P⋅l⋅<x> 3⋅P⋅<x> 5⋅P⋅<-l + x> P⋅<-2⋅l + x> ⎟ 0 ⎜ P⋅l⋅<x> 3⋅P⋅<x> 5⋅P⋅<-l + x> P⋅<-2⋅l + x> ⎟ 0
⎜────── - ───────────── + ───────────── - ─────────────⎟⋅<-2⋅l + x> ⎜- ──────── + ──────── - ───────────── + ─────────────⎟⋅<x> ⎜- ──────── + ──────── - ───────────── + ─────────────⎟⋅<-2⋅l + x>
⎝ 48 4 2 4 ⎠ ⎝ 4 8 8 4 ⎠ ⎝ 4 8 8 4 ⎠
──────────────────────────────────────────────────────────────────── + ──────────────────────────────────────────────────────────── - ───────────────────────────────────────────────────────────────────
E⋅I E⋅I E⋅I
>>> b.deflection()
⎛ 2 3 3 3⎞ ⎛ 2 3 3 3⎞ ⎛ 3 2 3 3 3⎞
⎜ P⋅l⋅<x> P⋅<x> 5⋅P⋅<-l + x> P⋅<-2⋅l + x> ⎟ 0 ⎜ P⋅l⋅<x> P⋅<x> 5⋅P⋅<-l + x> P⋅<-2⋅l + x> ⎟ 0 ⎜7⋅P⋅l 5⋅P⋅l ⋅(-2⋅l + x) P⋅<-2⋅l + x> P⋅<-3⋅l + x> P⋅<-4⋅l + x> ⎟ 0
⎜- ──────── + ────── - ───────────── + ─────────────⎟⋅<x> ⎜- ──────── + ────── - ───────────── + ─────────────⎟⋅<-2⋅l + x> ⎜────── + ───────────────── - ───────────── + ───────────── - ─────────────⎟⋅<-2⋅l + x>
⎝ 8 8 24 12 ⎠ ⎝ 8 8 24 12 ⎠ ⎝ 24 48 12 6 12 ⎠
────────────────────────────────────────────────────────── - ───────────────────────────────────────────────────────────────── + ────────────────────────────────────────────────────────────────────────────────────────
E⋅I E⋅I E⋅I
例 9
一个长度为 4 米的悬臂梁。前 2 米其截面惯性矩为 1.5*I,其余部分为 I。在其自由端施加了大小为 20 N 的点载荷。
---> x
\\\\| |
\\\\| 20 N v y
\\\\|________________ |
\\\\| |_______________V
\\\\| 1.5*I _______I_______|
\\\\|________________|
\\\\| :
\\\\|----------------|---------------|
2.0 m 2.0 m
>>> from sympy.physics.continuum_mechanics.beam import Beam
>>> from sympy import symbols
>>> E, I = symbols('E, I')
>>> R1, R2 = symbols('R1, R2')
>>> b1 = Beam(2, E, 1.5*I)
>>> b2 = Beam(2, E, I)
>>> b = b1.join(b2, "fixed")
>>> b.apply_load(20, 4, -1)
>>> b.apply_load(R1, 0, -1)
>>> b.apply_load(R2, 0, -2)
>>> b.bc_slope = [(0, 0)]
>>> b.bc_deflection = [(0, 0)]
>>> b.solve_for_reaction_loads(R1, R2)
>>> b.load
-2 -1 -1
80⋅<x> - 20⋅<x> + 20⋅<x - 4>
>>> b.shear_force()
-1 0 0
- 80⋅<x> + 20⋅<x> - 20⋅<x - 4>
>>> b.bending_moment()
0 1 1
- 80⋅<x> + 20⋅<x> - 20⋅<x - 4>
>>> b.slope()
⎛ 1 2 2 ⎞
⎜ - 80⋅<x> + 10⋅<x> - 10⋅<x - 4> 120 ⎟
⎜ ───────────────────────────────── + ─── ⎟ ⎛ 1 2 2⎞ 0 ⎛ 1 2 2⎞ 0
⎜ I I 80.0⎟ 0 0.666666666666667⋅⎝- 80⋅<x> + 10⋅<x> - 10⋅<x - 4> ⎠⋅<x> 0.666666666666667⋅⎝- 80⋅<x> + 10⋅<x> - 10⋅<x - 4> ⎠⋅<x - 2>
⎜- ─────────────────────────────────────── + ────⎟⋅<x - 2> - ────────────────────────────────────────────────────────── + ──────────────────────────────────────────────────────────────
⎝ E E⋅I ⎠ E⋅I E⋅I
例 10
一个组合梁,具有恒定的弯曲刚度 E*I,通过将长度为 2*l 的梁连接到另一长度为 l 的梁的右侧形成。整个梁在两端均固定。在距离起始点为 2*l 处还施加了大小为 P 的点载荷。
---> x
|
\\\\| P v y |\\\\
\\\\| | |\\\\
\\\\| V |\\\\
\\\\|____________ ________________________|\\\\
\\\\|____________O________________________|\\\\
\\\\| : : |\\\\
\\\\| : : |\\\\
\\\\|------------|------------|-----------|\\\\
l l l
>>> from sympy.physics.continuum_mechanics.beam import Beam
>>> from sympy import symbols
>>> E, I = symbols('E, I')
>>> l = symbols('l', positive=True)
>>> b1 = Beam(l ,E,I)
>>> b2 = Beam(2*l ,E,I)
>>> b = b1.join(b2,"hinge")
>>> M1, A1, M2, A2, P = symbols('M1 A1 M2 A2 P')
>>> b.apply_load(A1, 0, -1)
>>> b.apply_load(M1, 0 ,-2)
>>> b.apply_load(P, 2*l, -1)
>>> b.apply_load(A2, 3*l, -1)
>>> b.apply_load(M2, 3*l, -2)
>>> b.bc_slope=[(0, 0), (3*l, 0)]
>>> b.bc_deflection=[(0, 0), (3*l, 0)]
>>> b.solve_for_reaction_loads(M1, A1, M2, A2)
>>> b.reaction_loads
⎧ -5⋅P -13⋅P 5⋅P⋅l -4⋅P⋅l ⎫
⎨A₁: ─────, A₂: ──────, M₁: ─────, M₂: ───────⎬
⎩ 18 18 18 9 ⎭
>>> b.load
-2 -2 -1 -1
5⋅P⋅l⋅<x> 4⋅P⋅l⋅<-3⋅l + x> 5⋅P⋅<x> -1 13⋅P⋅<-3⋅l + x>
─────────── - ────────────────── - ───────── + P⋅<-2⋅l + x> - ─────────────────
18 9 18 18
>>> b.shear_force()
-1 -1 0 0
5⋅P⋅l⋅<x> 4⋅P⋅l⋅<-3⋅l + x> 5⋅P⋅<x> 0 13⋅P⋅<-3⋅l + x>
- ─────────── + ────────────────── + ──────── - P⋅<-2⋅l + x> + ────────────────
18 9 18 18
>>> b.bending_moment()
0 0 1 1
5⋅P⋅l⋅<x> 4⋅P⋅l⋅<-3⋅l + x> 5⋅P⋅<x> 1 13⋅P⋅<-3⋅l + x>
- ────────── + ───────────────── + ──────── - P⋅<-2⋅l + x> + ────────────────
18 9 18 18
>>> b.slope()
⎛ 1 2 2⎞ ⎛ 1 2 2⎞ ⎛ 2 1 2 2 2⎞
⎜5⋅P⋅l⋅<x> 5⋅P⋅<x> 5⋅P⋅<-l + x> ⎟ 0 ⎜5⋅P⋅l⋅<x> 5⋅P⋅<x> 5⋅P⋅<-l + x> ⎟ 0 ⎜P⋅l 4⋅P⋅l⋅<-3⋅l + x> 5⋅P⋅<-l + x> P⋅<-2⋅l + x> 13⋅P⋅<-3⋅l + x> ⎟ 0
⎜────────── - ──────── + ─────────────⎟⋅<x> ⎜────────── - ──────── + ─────────────⎟⋅<-l + x> ⎜──── - ───────────────── - ───────────── + ───────────── - ────────────────⎟⋅<-l + x>
⎝ 18 36 36 ⎠ ⎝ 18 36 36 ⎠ ⎝ 18 9 36 2 36 ⎠
──────────────────────────────────────────── - ───────────────────────────────────────────────── + ───────────────────────────────────────────────────────────────────────────────────────
E⋅I E⋅I E⋅I
>>> b.deflection()
⎛ 2 3 3⎞ ⎛ 2 3 3⎞ ⎛ 3 2 2 3 3 3⎞
⎜5⋅P⋅l⋅<x> 5⋅P⋅<x> 5⋅P⋅<-l + x> ⎟ 0 ⎜5⋅P⋅l⋅<x> 5⋅P⋅<x> 5⋅P⋅<-l + x> ⎟ 0 ⎜5⋅P⋅l P⋅l ⋅(-l + x) 2⋅P⋅l⋅<-3⋅l + x> 5⋅P⋅<-l + x> P⋅<-2⋅l + x> 13⋅P⋅<-3⋅l + x> ⎟ 0
⎜────────── - ──────── + ─────────────⎟⋅<x> ⎜────────── - ──────── + ─────────────⎟⋅<-l + x> ⎜────── + ───────────── - ───────────────── - ───────────── + ───────────── - ────────────────⎟⋅<-l + x>
⎝ 36 108 108 ⎠ ⎝ 36 108 108 ⎠ ⎝ 54 18 9 108 6 108 ⎠
──────────────────────────────────────────── - ───────────────────────────────────────────────── + ─────────────────────────────────────────────────────────────────────────────────────────────────────────
E⋅I E⋅I E⋅I
例 11
任何多项式定义的载荷均可施加到梁上。这允许近似任意的载荷分布。下面的例子展示了梁表面的六个截断多项式载荷。
>>> n = 6
>>> b = Beam(10*n, E, I)
>>> for i in range(n):
... b.apply_load(1 / (5**i), 10*i + 5, i, end=10*i + 10)
>>> plot(b.load, (x, 0, 10*n))
(png, hires.png, pdf)
桁架(文档字符串)
原文:
docs.sympy.org/latest/modules/physics/continuum_mechanics/truss.html
此模块可用于解决与二维桁架相关的问题。
class sympy.physics.continuum_mechanics.truss.Truss
桁架是由梁等成员组成的装配体,由节点连接,形成刚性结构。在工程中,桁架是仅由受力成员构成的结构。
桁架在工程应用中极为重要,并且可以在许多现实世界的应用中看到,如桥梁。
示例
一个桁架由四个节点和连接这些节点的五个成员组成。在节点 D 上作用向下的力 P,节点 A 和 B 上还存在固定和滚动关节。
>>> from sympy.physics.continuum_mechanics.truss import Truss
>>> t = Truss()
>>> t.add_node(("node_1", 0, 0), ("node_2", 6, 0), ("node_3", 2, 2), ("node_4", 2, 0))
>>> t.add_member(("member_1", "node_1", "node_4"), ("member_2", "node_2", "node_4"), ("member_3", "node_1", "node_3"))
>>> t.add_member(("member_4", "node_2", "node_3"), ("member_5", "node_3", "node_4"))
>>> t.apply_load(("node_4", 10, 270))
>>> t.apply_support(("node_1", "pinned"), ("node_2", "roller"))
add_member(*args)
此方法在给定桁架中任意两个节点之间添加成员。
参数:
此方法的输入是形如 (label, start, end) 的元组。
label: 字符串或符号
成员的标签。这是唯一识别特定成员的方式。
start: 字符串或符号
成员起点/节点的标签。
end: 字符串或符号
成员终点/节点的标签。
示例
>>> from sympy.physics.continuum_mechanics.truss import Truss
>>> t = Truss()
>>> t.add_node(('A', 0, 0), ('B', 3, 0), ('C', 2, 2))
>>> t.add_member(('AB', 'A', 'B'), ('BC', 'B', 'C'))
>>> t.members
{'AB': ['A', 'B'], 'BC': ['B', 'C']}
add_node(*args)
此方法向桁架添加节点及其名称/标签及其位置。可以同时添加多个节点。
参数:
此方法的输入是形如 (label, x, y) 的元组。
label: 字符串或符号
节点的标签。这是唯一识别特定节点的方式。
x: 可符号化
节点位置的 x 坐标。
y: 可符号化
节点位置的 y 坐标。
示例
>>> from sympy.physics.continuum_mechanics.truss import Truss
>>> t = Truss()
>>> t.add_node(('A', 0, 0))
>>> t.nodes
[('A', 0, 0)]
>>> t.add_node(('B', 3, 0), ('C', 4, 1))
>>> t.nodes
[('A', 0, 0), ('B', 3, 0), ('C', 4, 1)]
apply_load(*args)
此方法在指定节点处施加外部负载。
参数:
此方法的输入是形如 (location, magnitude, direction) 的元组。
location: 字符串或符号
负载应用于的节点的标签。
magnitude: 可符号化
施加的载荷大小。它必须始终为正,并且载荷方向的任何变化不反映在此处。
direction: 可符号化
负载向量与水平线逆时针方向的角度,单位为度。其取值范围为 0 到 360(含)。
示例
>>> from sympy.physics.continuum_mechanics.truss import Truss
>>> from sympy import symbols
>>> t = Truss()
>>> t.add_node(('A', 0, 0), ('B', 3, 0))
>>> P = symbols('P')
>>> t.apply_load(('A', P, 90), ('A', P/2, 45), ('A', P/4, 90))
>>> t.loads
{'A': [[P, 90], [P/2, 45], [P/4, 90]]}
apply_support(*args)
此方法在指定的节点添加固定或滚动支持。
参数:
此方法的输入是形如 (location, type) 的形式。
location: 字符串或符号
添加支持的节点的标签。
type: 字符串
提供的支持类型在节点。
示例
>>> from sympy.physics.continuum_mechanics.truss import Truss
>>> t = Truss()
>>> t.add_node(('A', 0, 0), ('B', 3, 0))
>>> t.apply_support(('A', 'pinned'), ('B', 'roller'))
>>> t.supports
{'A': 'pinned', 'B': 'roller'}
change_member_label(*args)
此方法更改指定成员的标签。
参数:
此方法的输入是形如 (label, new_label) 的元组。
label: 字符串或符号
需要更改其标签的成员的标签。
new_label: 字符串或符号
成员的新标签。
示例
>>> from sympy.physics.continuum_mechanics.truss import Truss
>>> t = Truss()
>>> t.add_node(('A', 0, 0), ('B', 3, 0), ('D', 5, 0))
>>> t.nodes
[('A', 0, 0), ('B', 3, 0), ('D', 5, 0)]
>>> t.change_node_label(('A', 'C'))
>>> t.nodes
[('C', 0, 0), ('B', 3, 0), ('D', 5, 0)]
>>> t.add_member(('BC', 'B', 'C'), ('BD', 'B', 'D'))
>>> t.members
{'BC': ['B', 'C'], 'BD': ['B', 'D']}
>>> t.change_member_label(('BC', 'BC_new'), ('BD', 'BD_new'))
>>> t.members
{'BC_new': ['B', 'C'], 'BD_new': ['B', 'D']}
change_node_label(*args)
此方法更改指定节点的标签。
参数:
此方法的输入是形式为 (标签, 新标签) 的元组。
标签:字符串或符号
需要更改标签的节点标签。
新标签:字符串或符号
节点的新标签。
示例
>>> from sympy.physics.continuum_mechanics.truss import Truss
>>> t = Truss()
>>> t.add_node(('A', 0, 0), ('B', 3, 0))
>>> t.nodes
[('A', 0, 0), ('B', 3, 0)]
>>> t.change_node_label(('A', 'C'), ('B', 'D'))
>>> t.nodes
[('C', 0, 0), ('D', 3, 0)]
draw(subs_dict=None)
返回带有所有节点、成员、支座和负载的桁架的绘图对象。
注意
用户在输入负载值及其方向时必须小心。绘制函数假设一种用于绘制负载的符号约定。
给定右手坐标系 XYZ 坐标,支座假设反应力对于固定支座在 +X 和 +Y 方向,对于滚动支座在 +Y 方向。对于负载,可输入的角度范围可以达到 360 度,这在绘图中是负载向量与正 x 轴逆时针方向的角度。
例如,对于 90 度角,负载将沿着 +Y 垂直方向,而 270 度角表示负载也是垂直的,但沿 -Y 方向。
示例
>>> from sympy.physics.continuum_mechanics.truss import Truss
>>> import math
>>> t = Truss()
>>> t.add_node(("A", -4, 0), ("B", 0, 0), ("C", 4, 0), ("D", 8, 0))
>>> t.add_node(("E", 6, 2/math.sqrt(3)))
>>> t.add_node(("F", 2, 2*math.sqrt(3)))
>>> t.add_node(("G", -2, 2/math.sqrt(3)))
>>> t.add_member(("AB","A","B"), ("BC","B","C"), ("CD","C","D"))
>>> t.add_member(("AG","A","G"), ("GB","G","B"), ("GF","G","F"))
>>> t.add_member(("BF","B","F"), ("FC","F","C"), ("CE","C","E"))
>>> t.add_member(("FE","F","E"), ("DE","D","E"))
>>> t.apply_support(("A","pinned"), ("D","roller"))
>>> t.apply_load(("G", 3, 90), ("E", 3, 90), ("F", 2, 90))
>>> p = t.draw()
>>> p
Plot object containing:
[0]: cartesian line: 1 for x over (1.0, 1.0)
...
>>> p.show()
(png, hires.png, pdf)
property internal_forces
返回所有初始化为 0 的成员的内力。
property loads
返回作用在桁架上的负载。
property member_lengths
返回桁架每个成员的长度。
property members
返回桁架成员及其起点和终点。
property node_labels
返回桁架节点标签。
property node_positions
返回桁架节点的位置。
property nodes
返回桁架节点及其位置。
property reaction_loads
返回所有初始化为 0 的支座的反力。
remove_load(*args)
此方法移除指定节点上已存在的外部负载。
参数:
此方法的输入是形式为 (位置, 大小, 方向) 的元组。
位置:字符串或符号
应用负载的节点标签,即将被移除。
magnitude: 可符号化
应用负载的大小。
direction: 可符号化
负载向量与水平方向逆时针方向的角度,以度为单位,取值范围为 0 到 360(包括边界)。
示例
>>> from sympy.physics.continuum_mechanics.truss import Truss
>>> from sympy import symbols
>>> t = Truss()
>>> t.add_node(('A', 0, 0), ('B', 3, 0))
>>> P = symbols('P')
>>> t.apply_load(('A', P, 90), ('A', P/2, 45), ('A', P/4, 90))
>>> t.loads
{'A': [[P, 90], [P/2, 45], [P/4, 90]]}
>>> t.remove_load(('A', P/4, 90), ('A', P/2, 45))
>>> t.loads
{'A': [[P, 90]]}
remove_member(*args)
此方法从给定桁架中移除成员。
参数:
labels: 字符串或符号
要移除的成员的标签。
示例
>>> from sympy.physics.continuum_mechanics.truss import Truss
>>> t = Truss()
>>> t.add_node(('A', 0, 0), ('B', 3, 0), ('C', 2, 2))
>>> t.add_member(('AB', 'A', 'B'), ('AC', 'A', 'C'), ('BC', 'B', 'C'))
>>> t.members
{'AB': ['A', 'B'], 'AC': ['A', 'C'], 'BC': ['B', 'C']}
>>> t.remove_member('AC', 'BC')
>>> t.members
{'AB': ['A', 'B']}
remove_node(*args)
此方法从桁架中移除一个节点。可以同时移除多个节点。
参数:
此方法的输入是要移除的节点的标签。
label: 字符串或符号
要移除的节点标签。
示例
>>> from sympy.physics.continuum_mechanics.truss import Truss
>>> t = Truss()
>>> t.add_node(('A', 0, 0), ('B', 3, 0), ('C', 5, 0))
>>> t.nodes
[('A', 0, 0), ('B', 3, 0), ('C', 5, 0)]
>>> t.remove_node('A', 'C')
>>> t.nodes
[('B', 3, 0)]
remove_support(*args)
此方法从指定节点移除支座。
参数:
位置:字符串或符号
支座要移除的节点的标签。
示例
>>> from sympy.physics.continuum_mechanics.truss import Truss
>>> t = Truss()
>>> t.add_node(('A', 0, 0), ('B', 3, 0))
>>> t.apply_support(('A', 'pinned'), ('B', 'roller'))
>>> t.supports
{'A': 'pinned', 'B': 'roller'}
>>> t.remove_support('A','B')
>>> t.supports
{}
solve()
此方法解决了所有支座的所有反力和梁架所有构件的所有内力,前提是梁架是可解的。
如果满足以下条件,梁架是可解的,
2n >= r + m
其中 n 是节点数,r 是反力的数量,每个铰支座有 2 个反力,每个滚动支座有 1 个,m 是构件数。
给定条件源于一个事实,即只有当变量数小于或等于方程数时,方程组才可解。在 x 和 y 方向的平衡方程为每个节点提供两个方程,总共提供了 2n 个方程。然而,梁架还需要保持稳定,如果 2n > r + m,则可能不稳定。变量数简单地是反力数和构件力的总和。
注意
关于构件中存在的内力的符号约定是关于每个力是压缩力还是拉伸力的。在为每个节点形成方程时,假定每个构件对节点的内力是远离节点的,即默认情况下每个力都是压缩力。因此,内力的正值意味着构件中存在压缩力,负值意味着拉伸力。
例子
>>> from sympy.physics.continuum_mechanics.truss import Truss
>>> t = Truss()
>>> t.add_node(("node_1", 0, 0), ("node_2", 6, 0), ("node_3", 2, 2), ("node_4", 2, 0))
>>> t.add_member(("member_1", "node_1", "node_4"), ("member_2", "node_2", "node_4"), ("member_3", "node_1", "node_3"))
>>> t.add_member(("member_4", "node_2", "node_3"), ("member_5", "node_3", "node_4"))
>>> t.apply_load(("node_4", 10, 270))
>>> t.apply_support(("node_1", "pinned"), ("node_2", "roller"))
>>> t.solve()
>>> t.reaction_loads
{'R_node_1_x': 0, 'R_node_1_y': 20/3, 'R_node_2_y': 10/3}
>>> t.internal_forces
{'member_1': 20/3, 'member_2': 20/3, 'member_3': -20*sqrt(2)/3, 'member_4': -10*sqrt(5)/3, 'member_5': 10}
property supports
返回提供的支持节点以及所提供支持的类型,即铰链或滚动支持。
电缆(文档字符串)
原文:
docs.sympy.org/latest/modules/physics/continuum_mechanics/cable.html
电缆
此模块可用于解决与 2D 电缆相关的问题。
class sympy.physics.continuum_mechanics.cable.Cable(support_1, support_2)
电缆是工程中的结构,通过其成员发展的拉伸阻力支持施加的横向载荷。
电缆广泛用于悬索桥、张力腿海上平台、输电线路等,同时在几个其他工程应用中使用。
实例
电缆在(0, 10)和(10, 10)处支持。两个垂直向下作用的点负载作用在电缆上,一个大小为 3 kN,距离左支持 2 米,下方 3 米,另一个大小为 2 kN,距离左支持 6 米,下方 6 米。
>>> from sympy.physics.continuum_mechanics.cable import Cable
>>> c = Cable(('A', 0, 10), ('B', 10, 10))
>>> c.apply_load(-1, ('P', 2, 7, 3, 270))
>>> c.apply_load(-1, ('Q', 6, 4, 2, 270))
>>> c.loads
{'distributed': {}, 'point_load': {'P': [3, 270], 'Q': [2, 270]}}
>>> c.loads_position
{'P': [2, 7], 'Q': [6, 4]}
apply_length(length)
此方法指定电缆的长度
参数:
长度:Sympifyable
电缆的长度
实例
>>> from sympy.physics.continuum_mechanics.cable import Cable
>>> c = Cable(('A', 0, 10), ('B', 10, 10))
>>> c.apply_length(20)
>>> c.length
20
apply_load(order, load)
此方法向电缆添加负载。
参数:
顺序:整数
施加负载的顺序。
- 对于点负载,顺序= -1
- 对于分布负载,顺序= 0
负载:元组
- 对于点载荷,负载的形式为(标签,x,y,大小,方向),其中:
labelString 或符号
负载的标签
xSympifyable
负载位置的 x 坐标
ySympifyable
负载位置的 y 坐标
magnitudeSympifyable
负载的大小。它必须始终为正值
directionSympifyable
负载矢量与水平方向逆时针方向的角度,以度为单位。取值范围为 0 到 360,包括 0 和 360。
- 对于均匀分布的负载,负载的形式为(标签,大小)
labelString 或符号
负载的标签
magnitudeSympifyable
负载的大小。它必须始终为正值
实例
对于水平方向与负载的数量为 12 个单位的点负载:
>>> from sympy.physics.continuum_mechanics.cable import Cable
>>> c = Cable(('A', 0, 10), ('B', 10, 10))
>>> c.apply_load(-1, ('Z', 5, 5, 12, 30))
>>> c.loads
{'distributed': {}, 'point_load': {'Z': [12, 30]}}
>>> c.loads_position
{'Z': [5, 5]}
对于大小为 9 单位的均匀分布负载:
>>> from sympy.physics.continuum_mechanics.cable import Cable
>>> c = Cable(('A', 0, 10), ('B', 10, 10))
>>> c.apply_load(0, ('X', 9))
>>> c.loads
{'distributed': {'X': 9}, 'point_load': {}}
change_support(label, new_support)
此方法用新支持更改了提到的支持。
参数:
标签:字符串或符号
要更改的支持的标签
new_support:形式为(new_label,x,y)的元组
new_label:字符串或符号
新支持的标签
x:Sympifyable
新支持位置的 x 坐标。
y:Sympifyable
新支持位置的 y 坐标。
实例
>>> from sympy.physics.continuum_mechanics.cable import Cable
>>> c = Cable(('A', 0, 10), ('B', 10, 10))
>>> c.supports
{'A': [0, 10], 'B': [10, 10]}
>>> c.change_support('B', ('C', 5, 6))
>>> c.supports
{'A': [0, 10], 'C': [5, 6]}
property left_support
返回左支持的位置。
property length
返回电缆的长度。
property loads
返回作用在电缆上的负载的大小和方向。
property loads_position
返回作用在电缆上的点载荷的位置。
property reaction_loads
返回支持处初始化为 0 的反应力。
remove_loads(*args)
此方法删除指定的负载。
参数:
此输入接受多个标签作为输入
标签:字符串或符号
要移除的负载的标签。
实例
>>> from sympy.physics.continuum_mechanics.cable import Cable
>>> c = Cable(('A', 0, 10), ('B', 10, 10))
>>> c.apply_load(-1, ('Z', 5, 5, 12, 30))
>>> c.loads
{'distributed': {}, 'point_load': {'Z': [12, 30]}}
>>> c.remove_loads('Z')
>>> c.loads
{'distributed': {}, 'point_load': {}}
property right_support
返回右侧支持的位置。
solve(*args)
此方法求解支持处的反应力、电缆中发展的张力,并更新电缆的长度。
参数:
在解决点载荷时,此方法不需要输入
对于分布载荷,电缆最低点的 x 和 y 坐标为
作为所需的
x:可合成
电缆最低点的 x 坐标
y:可合成
电缆最低点的 y 坐标
示例
对于点载荷,
>>> from sympy.physics.continuum_mechanics.cable import Cable
>>> c = Cable(("A", 0, 10), ("B", 10, 10))
>>> c.apply_load(-1, ('Z', 2, 7.26, 3, 270))
>>> c.apply_load(-1, ('X', 4, 6, 8, 270))
>>> c.solve()
>>> c.tension
{A_Z: 8.91403453669861, X_B: 19*sqrt(13)/10, Z_X: 4.79150773600774}
>>> c.reaction_loads
{R_A_x: -5.25547445255474, R_A_y: 7.2, R_B_x: 5.25547445255474, R_B_y: 3.8}
>>> c.length
5.7560958484519 + 2*sqrt(13)
对于分布载荷,
>>> from sympy.physics.continuum_mechanics.cable import Cable
>>> c=Cable(("A", 0, 40),("B", 100, 20))
>>> c.apply_load(0, ("X", 850))
>>> c.solve(58.58, 0)
>>> c.tension
{'distributed': 36456.8485*sqrt(0.000543529004799705*(X + 0.00135624381275735)**2 + 1)}
>>> c.tension_at(0)
61709.0363315913
>>> c.reaction_loads
{R_A_x: 36456.8485, R_A_y: -49788.5866682485, R_B_x: 44389.8401587246, R_B_y: 42866.621696333}
property supports
返回电缆的支持点及其位置。
property tension
返回由施加的载荷引起的电缆张力。
tension_at(x)
返回由分布载荷引起的给定 x 值处的张力。
实用工具
原文:
docs.sympy.org/latest/reference/public/utilities/index.html
内容
-
测试
-
pytest
-
随机化测试
-
运行测试
-
-
实用工具
-
自动包装模块
-
代码生成
-
装饰器
-
枚举
-
异常和警告
-
可迭代对象
-
Lambda 函数化
-
记忆化
-
杂项
-
源代码检查
-
时间工具
-
-
交互式
-
解析
-
打印
测试
此模块包含用于在 SymPy 中运行测试的代码。
内容:
-
pytest
-
随机化测试
-
运行测试
pytest
py.test 的 hack 来支持 XFAIL/XPASS
sympy.testing.pytest.SKIP(reason)
与skip()类似,但这是一个装饰器。
sympy.testing.pytest.nocache_fail(func)
用于标记在禁用缓存时失败的测试的虚拟装饰器
sympy.testing.pytest.raises(expectedException, code=None)
测试code是否引发了异常expectedException。
code可以是可调用对象,比如 lambda 表达式或函数名。
如果未提供code或为None,raises将返回一个供with语句使用的上下文管理器;然后执行的代码来自with的范围。
如果可调用对象引发了预期的异常,raises()不会执行任何操作,否则会引发 AssertionError。
示例
>>> from sympy.testing.pytest import raises
>>> raises(ZeroDivisionError, lambda: 1/0)
<ExceptionInfo ZeroDivisionError(...)>
>>> raises(ZeroDivisionError, lambda: 1/2)
Traceback (most recent call last):
...
Failed: DID NOT RAISE
>>> with raises(ZeroDivisionError):
... n = 1/0
>>> with raises(ZeroDivisionError):
... n = 1/2
Traceback (most recent call last):
...
Failed: DID NOT RAISE
请注意,你不能通过with raises来测试多个语句:
>>> with raises(ZeroDivisionError):
... n = 1/0 # will execute and raise, aborting the ``with``
... n = 9999/0 # never executed
这正是with应该做的:在第一个异常处中止包含的语句序列,并让上下文管理器处理异常。
要测试多个语句,每个语句都需要单独的with:
>>> with raises(ZeroDivisionError):
... n = 1/0 # will execute and raise
>>> with raises(ZeroDivisionError):
... n = 9999/0 # will also execute and raise
sympy.testing.pytest.skip_under_pyodide(message)
用于在 pyodide 下运行时跳过测试的装饰器。
sympy.testing.pytest.warns(warningcls, *, match='', test_stacklevel=True)
类似raises,但测试是否发出了警告。
>>> from sympy.testing.pytest import warns
>>> import warnings
>>> with warns(UserWarning):
... warnings.warn('deprecated', UserWarning, stacklevel=2)
>>> with warns(UserWarning):
... pass
Traceback (most recent call last):
...
Failed: DID NOT WARN. No warnings of type UserWarning was emitted. The list of emitted warnings is: [].
test_stacklevel使其检查warn()的stacklevel参数是否设置,以便警告显示用户代码行(在warns()上下文管理器下的代码)。如果这不明确或者上下文管理器不测试直接发出警告的用户代码,则将其设置为 False。
如果警告是SymPyDeprecationWarning,这还会测试active-deprecations.md文件中的active_deprecations_target是否是一个真实的目标。
sympy.testing.pytest.warns_deprecated_sympy()
warns(SymPyDeprecationWarning)的简写
这是在 SymPy 中测试已弃用功能是否发出SymPyDeprecationWarning的推荐方式。要测试其他警告,请使用warns。要在不断言它们被发出的情况下抑制警告,请使用ignore_warnings。
注意
warns_deprecated_sympy()仅用于 SymPy 测试套件中内部使用,以测试是否正确触发了弃用警告。SymPy 代码库中的所有其他代码,包括文档示例,都不应使用弃用的行为。
如果你是 SymPy 的用户,想要禁用 SymPyDeprecationWarnings,请使用警告过滤器(参见 Silencing SymPy Deprecation Warnings)。
>>> from sympy.testing.pytest import warns_deprecated_sympy
>>> from sympy.utilities.exceptions import sympy_deprecation_warning
>>> with warns_deprecated_sympy():
... sympy_deprecation_warning("Don't use",
... deprecated_since_version="1.0",
... active_deprecations_target="active-deprecations")
>>> with warns_deprecated_sympy():
... pass
Traceback (most recent call last):
...
Failed: DID NOT WARN. No warnings of type SymPyDeprecationWarning was emitted. The list of emitted warnings is: [].
注意
有时堆栈级别测试会失败,因为同一个警告被多次发出。在这种情况下,你可以在代码中使用sympy.utilities.exceptions.ignore_warnings()来防止SymPyDeprecationWarning再次递归发出。在某些情况下,对于废弃警告,可能无法有一个一致的stacklevel,因为不同的调用函数方式会产生不同的调用堆栈。在这些情况下,请改用warns(SymPyDeprecationWarning)。
另请参阅
sympy.utilities.exceptions.SymPyDeprecationWarning, sympy.utilities.exceptions.sympy_deprecation_warning, sympy.utilities.decorator.deprecated
随机化测试
自 1.10 版起不建议使用:sympy.testing.randtest 函数已移至sympy.core.random。
运行测试
这是我们的测试框架。
目标:
-
它应与 py.test 兼容,并且操作方式非常相似(或完全相同)
-
不需要任何外部依赖
-
最好所有功能都在此文件中
-
没有魔法,只需导入测试文件并执行测试函数,就这样
-
可移植
class sympy.testing.runtests.PyTestReporter(verbose=False, tb='short', colors=True, force_colors=False, split=None)
像 Py.test 一样的报告者。应该生成与 py.test 完全相同的输出。
write(text, color='', align='left', width=None, force_colors=False)
在屏幕上打印文本。
它使用 sys.stdout.write(),因此不需要 readline 库。
参数:
颜色:从下面的颜色中选择,“” 表示默认颜色
对齐:“left”/“right”,“left” 是正常打印,“right” 是右对齐
屏幕右侧,必要时填充空格
宽度:屏幕宽度
class sympy.testing.runtests.Reporter
所有报告者的父类。
class sympy.testing.runtests.SymPyDocTestFinder(verbose=False, parser=<doctest.DocTestParser object>, recurse=True, exclude_empty=True)
用于提取与给定对象相关的 DocTest 的类,从其文档字符串及其包含对象的文档字符串中。目前可以从以下对象类型中提取 DocTest:模块、函数、类、方法、静态方法、类方法和属性。
修改自 doctest 版本,更加努力地查找看起来来自不同模块的代码。例如,@vectorize 装饰器使得函数看起来来自 multidimensional.py,尽管它们的代码存在于其他地方。
class sympy.testing.runtests.SymPyDocTestRunner(checker=None, verbose=None, optionflags=0)
用于运行 DocTest 测试用例并累积统计信息的类。run 方法用于处理单个 DocTest 用例。它返回一个元组 (f, t),其中 t 是尝试的测试用例数,f 是失败的测试用例数。
修改自 doctest 版本,以不重置 sys.displayhook(参见问题 5140)。
查看原始 DocTestRunner 的文档字符串以获取更多信息。
run(test, compileflags=None, out=None, clear_globs=True)
运行在 test 中的示例,并使用写入函数 out 显示结果。
示例在命名空间 test.globs 中运行。如果 clear_globs 为 true(默认值),则在测试运行后将清除此命名空间,以帮助垃圾收集。如果您希望在测试完成后检查命名空间,请使用 clear_globs=False。
compileflags 给出了 Python 编译器在运行示例时应使用的标志集。如果未指定,则默认为适用于 globs 的未来导入标志集。
每个示例的输出都使用 SymPyDocTestRunner.check_output 进行检查,并由 SymPyDocTestRunner.report_* 方法进行格式化。
class sympy.testing.runtests.SymPyOutputChecker
与 stdlib 中的 OutputChecker 相比,我们的 OutputChecker 类支持对 doctest 示例输出中出现的浮点数进行数值比较。
check_output(want, got, optionflags)
如果来自示例的实际输出((got))与预期输出((want))匹配,则返回 True。如果它们完全相同,则始终认为这些字符串匹配;但根据测试运行器使用的选项标志,还可能存在几种非精确匹配类型。有关选项标志的更多信息,请参阅(TestRunner)的文档。
class sympy.testing.runtests.SymPyTestResults(failed, attempted)
attempted
字段编号 1 的别名
failed
字段编号 0 的别名
sympy.testing.runtests.convert_to_native_paths(lst)
将一组由‘/’分隔的路径转换为本地(os.sep 分隔)路径列表,并在系统不区分大小写时转换为小写。
sympy.testing.runtests.doctest(*paths, subprocess=True, rerun=0, **kwargs)
运行 SymPy 目录中所有与paths中给定字符串匹配的*.py 文件中的 doctests,或者如果 paths=[]则运行所有测试。
注意:
-
路径可以输入本地系统格式或 unix,正斜杠格式。
-
黑名单中的文件可以通过提供其路径来进行测试;只有在没有给定路径的情况下才会排除它们。
示例
>>> import sympy
运行所有测试:
>>> sympy.doctest()
运行一个文件:
>>> sympy.doctest("sympy/core/basic.py")
>>> sympy.doctest("polynomial.rst")
在 sympy/functions/中运行所有测试以及某个特定文件:
>>> sympy.doctest("/functions", "basic.py")
运行任何文件名中包含多项式的文件,doc/src/modules/polynomial.rst,sympy/functions/special/polynomials.py 以及 sympy/polys/polynomial.py:
>>> sympy.doctest("polynomial")
可以传递split选项来将测试运行分成多个部分。目前只会将测试文件分割,但这可能会在将来改变。split应该是形式为‘a/b’的字符串,将运行第a部分的b。请注意,常规 doctests 和 Sphinx doctests 会独立拆分。例如,要运行测试套件的前一半:
>>> sympy.doctest(split='1/2')
subprocess 和 verbose 选项与函数 test() 中的相同(有关更多信息,请参阅该函数的文档字符串),不同之处在于 verbose 还可以设置为 2,以打印单独的 doctest 行,因为它们正在被测试。
sympy.testing.runtests.get_sympy_dir()
返回根 SymPy 目录并设置全局值,指示系统是否区分大小写。
sympy.testing.runtests.raise_on_deprecated()
上下文管理器,使 DeprecationWarning 引发错误
在运行测试和 doctests 时捕获来自库代码的 SymPyDeprecationWarning,并使用此上下文管理器尤为重要,以防一些测试修改了警告过滤器。
sympy.testing.runtests.run_all_tests(test_args=(), test_kwargs=None, doctest_args=(), doctest_kwargs=None, examples_args=(), examples_kwargs=None)
运行所有测试。
目前,此操作运行常规测试(bin/test)、doctests(bin/doctest)和示例(examples/all.py)。
这是setup.py test使用的内容。
您可以将参数和关键字参数传递给支持它们的测试函数(目前为止,测试、doctest 和示例)。有关可用选项的描述,请参阅这些函数的文档字符串。
例如,要在关闭颜色的情况下运行求解器测试:
>>> from sympy.testing.runtests import run_all_tests
>>> run_all_tests(test_args=("solvers",),
... test_kwargs={"colors:False"})
sympy.testing.runtests.run_in_subprocess_with_hash_randomization(function, function_args=(), function_kwargs=None, command='/opt/hostedtoolcache/Python/3.12.3/x64/bin/python', module='sympy.testing.runtests', force=False)
使用启用哈希随机化的 Python 子进程运行函数。
如果给定的 Python 版本不支持哈希随机化,则返回 False。否则,返回命令的退出值。该函数传递给 sys.exit(),因此函数的返回值将是返回值。
环境变量 PYTHONHASHSEED 用于种子化 Python 的哈希随机化。如果设置了它,此函数将返回 False,因为在这种情况下启动新子进程是不必要的。如果未设置,则随机设置一个种子,并运行测试。请注意,如果 Python 启动时设置了此环境变量,则哈希随机化将自动启用。要强制创建子进程,即使设置了 PYTHONHASHSEED,请传递force=True。在不支持哈希随机化的 Python 版本中(请参阅下文),此标志将不会强制创建子进程,因为这些 Python 版本不支持-R标志。
function应该是一个从模块module可导入的函数的字符串名称,例如“_test”。function_args和function_kwargs应该分别是 repr-able 的元组和字典。默认的 Python 命令是 sys.executable,即当前正在运行的 Python 命令。
此函数是必需的,因为在 Python 启动之前必须通过环境变量设置哈希随机化的种子。因此,为了在测试中使用预定的种子,我们必须在一个单独的子进程中启动 Python。
哈希随机化添加在次要 Python 版本 2.6.8、2.7.3、3.1.5 和 3.2.3 中,并且在包括 3.3.0 及以后的所有 Python 版本中默认启用。
示例
>>> from sympy.testing.runtests import (
... run_in_subprocess_with_hash_randomization)
>>> # run the core tests in verbose mode
>>> run_in_subprocess_with_hash_randomization("_test",
... function_args=("core",),
... function_kwargs={'verbose': True})
# Will return 0 if sys.executable supports hash randomization and tests
# pass, 1 if they fail, and False if it does not support hash
# randomization.
sympy.testing.runtests.split_list(l, split, density=None)
将列表分割为 a 部分的 b 部分
split 应该是形式为‘a/b’的字符串。例如,‘1/3’将给出一个三分之一的分割。
如果列表的长度不能被分割数整除,则最后一个分割将具有更多的项。
(density)可以指定为一个列表。如果指定了,则根据(density)平衡测试,以便每个分割具有尽可能相等的质量。
>>> from sympy.testing.runtests import split_list
>>> a = list(range(10))
>>> split_list(a, '1/3')
[0, 1, 2]
>>> split_list(a, '2/3')
[3, 4, 5]
>>> split_list(a, '3/3')
[6, 7, 8, 9]
sympy.testing.runtests.sympytestfile(filename, module_relative=True, name=None, package=None, globs=None, verbose=None, report=True, optionflags=0, extraglobs=None, raise_on_error=False, parser=<doctest.DocTestParser object>, encoding=None)
给定文件中的测试示例。返回(#失败,#测试)。
可选关键字参数module_relative指定文件名的解释方式:
-
如果
module_relative为 True(默认值),则filename指定一个模块相对路径。默认情况下,此路径相对于调用模块的目录;但如果指定了package参数,则相对于该包。为确保操作系统的独立性,filename应使用“/”字符分隔路径段,并且不应为绝对路径(即,不能以“/”开头)。 -
如果
module_relative为 False,则filename指定一个特定于操作系统的路径。路径可以是绝对的或相对的(相对于当前工作目录)。
可选关键字参数name给出测试的名称;默认使用文件的基本名称。
可选关键字参数package是一个 Python 包或 Python 包的名称,其目录应作为模块相对文件名的基本目录。如果未指定包,则使用调用模块的目录作为模块相对文件名的基本目录。如果module_relative为 False,则指定package是一个错误。
可选关键字参数globs提供一个应用于执行示例时用作全局变量的字典;默认使用{}。实际上为每个 docstring 的副本使用此字典,以便每个 docstring 的示例都从干净的状态开始。
可选关键字参数extraglobs提供一个应合并到用于执行示例的全局变量中的字典。默认情况下不使用额外的全局变量。
可选关键字参数verbose如果为真,则打印大量内容;如果为假,则仅打印失败项。默认情况下,如果 sys.argv 中包含“-v”,则为真。
可选关键字参数report在为 true 时打印摘要结束时打印,否则在结束时打印空白(如果所有测试都通过,则为空白)。
可选关键字参数optionflags将模块常量或在一起,并默认为 0。可能的值(详见文档详细信息):
-
DONT_ACCEPT_TRUE_FOR_1
-
DONT_ACCEPT_BLANKLINE
-
NORMALIZE_WHITESPACE
-
ELLIPSIS
-
SKIP
-
IGNORE_EXCEPTION_DETAIL
-
REPORT_UDIFF
-
REPORT_CDIFF
-
REPORT_NDIFF
-
REPORT_ONLY_FIRST_FAILURE
可选关键字参数raise_on_error在第一个意外异常或失败时引发异常。这允许将失败后调试。
可选关键字参数parser指定应用于从文件中提取测试的 DocTestParser(或其子类)。
可选关键字参数encoding指定用于将文件转换为 Unicode 的编码。
高级愚蠢行为:testmod 运行本地类实例 doctest.Tester 的方法,然后将结果合并到(或创建)全局 Tester 实例 doctest.master 中。您也可以直接调用 doctest.master 的方法,如果您想做一些不寻常的事情。将 report=0 传递给 testmod 在这种情况下特别有用,以延迟显示摘要。完成调整后调用 doctest.master.summarize(verbose)。
sympy.testing.runtests.test(*paths, subprocess=True, rerun=0, **kwargs)
在指定的 test_*.py 文件中运行测试。
如果paths=[],则如果paths中的任何给定字符串与测试文件的路径的一部分匹配,则在特定 test_.py 文件中运行测试。将在所有 test_.py 文件中运行测试。
注意:
-
如果 sort=False,则按随机顺序(而不是默认顺序)运行测试。
-
路径可以输入本地系统格式或 Unix 前斜杠格式。
-
提供路径测试的文件可以通过提供其路径进行测试;仅在没有给出路径时才排除它们。
测试结果的解释
| Output | Meaning |
|---|---|
| . | passed |
| F | failed |
| X | XPassed(预期会失败但通过) |
| f | XFAILed(预期会失败并确实失败) |
| s | skipped |
| w | slow |
| T | timeout(例如,当使用--timeout时) |
| K | KeyboardInterrupt(当使用--slow运行缓慢测试时,您可以中断其中一个,而不会终止测试运行器) |
颜色没有额外的含义,只是用于便于解释输出。
示例
>>> import sympy
运行所有测试:
>>> sympy.test()
运行一个文件:
>>> sympy.test("sympy/core/tests/test_basic.py")
>>> sympy.test("_basic")
运行 sympy/functions/中的所有测试和某个特定文件:
>>> sympy.test("sympy/core/tests/test_basic.py",
... "sympy/functions")
运行 sympy/core 和 sympy/utilities 中的所有测试:
>>> sympy.test("/core", "/util")
从文件中运行特定测试:
>>> sympy.test("sympy/core/tests/test_basic.py",
... kw="test_equality")
从任何文件中运行特定测试:
>>> sympy.test(kw="subs")
使用详细模式运行测试:
>>> sympy.test(verbose=True)
不要对测试输出排序:
>>> sympy.test(sort=False)
打开事后调试 pdb:
>>> sympy.test(pdb=True)
关闭颜色:
>>> sympy.test(colors=False)
即使输出不是终端,也要强制使用颜色(例如,如果您正在将其管道到less -r并且仍然想要颜色)。
>>> sympy.test(force_colors=False)
可以将回溯详细程度设置为“short”或“no”(默认为“short”)。
>>> sympy.test(tb='no')
可以传递split选项来将测试运行分成几部分。目前,分割仅分割测试文件,但这可能会在将来更改。split应该是形式为‘a/b’的字符串,这将运行第a部分的b。例如,要运行测试套件的前半部分:
>>> sympy.test(split='1/2')
可以与split一起传递time_balance选项。如果time_balance=True(sympy.test的默认值),SymPy 将尝试分割测试,以使每个分割花费相等的时间。这种平衡的启发式基于预先记录的测试数据。
>>> sympy.test(split='1/2', time_balance=True)
可以通过设置subprocess=False来禁用在单独的子进程中运行测试。这样做是为了支持种子哈希随机化,在支持的 Python 版本中默认启用。如果subprocess=False,则哈希随机化根据调用的 Python 进程是否启用来启用/禁用。但是,即使启用了哈希随机化,除非从新的 Python 进程调用,否则无法打印种子。
哈希随机化是在次要 Python 版本 2.6.8、2.7.3、3.1.5 和 3.2.3 中添加的,并且默认情况下在包括 3.3.0 及以后的所有 Python 版本中启用。
如果不支持哈希随机化,则自动使用subprocess=False。
>>> sympy.test(subprocess=False)
要设置哈希随机化种子,请在运行测试之前设置环境变量PYTHONHASHSEED。这可以在 Python 内部使用
>>> import os
>>> os.environ['PYTHONHASHSEED'] = '42'
或者从命令行使用
$ PYTHONHASHSEED=42 ./bin/test
如果未设置种子,则将选择一个随机种子。
注意,要重现相同的哈希值,必须同时使用相同的种子和相同的架构(32 位 vs 64 位)。