SymPy Arch 模块实战:使用 Python 完成二维抛物线三铰拱的建模、加载与内力分析
SymPy Arch 模块实战使用 Python 完成二维抛物线三铰拱的建模、加载与内力分析【免费下载链接】sympyA computer algebra system written in pure Python项目地址: https://gitcode.com/GitHub_Trending/sy/sympy本篇技术指南围绕 SymPy 连续介质力学模块sympy.physics.continuum_mechanics中的Arch类展开讲解如何用纯 Python 对二维抛物线三铰拱three-hinged arch静定结构进行几何建模、施加集中/分布荷载、求解支座反力与内力弯矩、剪力、轴力并完成可视化。读完本文你将掌握Arch的完整 API 调用方式、支撑/铰点配置规则与源码级实现原理可以直接用于结构力学课程作业、桥拱初步分析等场景。Arch 模块在 SymPy 中的定位Arch类是 SymPy 连续介质力学子包中与Beam、Truss、Cable并列的结构分析工具位于 sympy/physics/continuum_mechanics/arch.py。模块文件开头的 docstring 明确其用途This module can be used to solve problems related to 2D parabolic arches本模块用于求解与二维抛物线拱相关的问题。在 sympy/physics/continuum_mechanics/init.py 中Arch与其他三个类一同被导出因此有两种等价导入方式# 方式一从 arch 子模块导入官方 docstring 中的写法 from sympy.physics.continuum_mechanics.arch import Arch # 方式二从 continuum_mechanics 包直接导入经由 __init__.py 的 __all__ 导出 from sympy.physics.continuum_mechanics import Arch本模块的官方文档页位于 doc/src/modules/physics/continuum_mechanics/arches.rst采用 Sphinxautomodule指令自动渲染类与全部方法的 docstring它在 doc/src/modules/physics/continuum_mechanics/index.rst 中被组织进「Continuum Mechanics」文档树。拱结构建模的基本概念Arch类用于求解**三铰拱three-hinged arch**问题——即两端各有一个支座铰、拱顶冠部还有一个铰的静定结构。类的 docstring 给出了背景拱是一种横跨其下开放空间的弯曲竖向结构over windows、door 甚至 bridges拱能够承担放置于其上方的很大质量因此在长跨度结构中被用于减小弯矩reduce the bending moments in long-span structures。建模时需要输入的关键几何要素有四个要素含义说明left_support左支座坐标(x, y)构造时必填right_support右支座坐标(x, y)构造时必填crown_x拱顶铰crown/hinge的 x 坐标必填不填会抛KeyErrorcrown_y拱顶铰的 y 坐标可选不填则通过左右支座联立求解构造拱并获取形状方程基础构造最简单的构造方式是同时给定两个支座与冠部坐标from sympy.physics.continuum_mechanics.arch import Arch a Arch((0, 0), (10, 0), crown_x5, crown_y5) a.get_shape_eqn # 输出5 - (x - 5)**2/5也可以只给出crown_x让冠部 y 坐标由左右支座坐标联立确定a Arch((0, 0), (10, 1), crown_x6) a.get_shape_eqn # 输出9/5 - (x - 6)**2/20构造后可通过只读属性查看基本几何信息left_support、right_support、supports等属性均返回元组/字典见 arch.py 源码 L107-L140a.left_support # (0, 0) a.right_support # (10, 1) a.supports # {left: hinge, right: hinge} 默认两端均为铰支座形状方程推导的源码原理get_shape_eqn是核心属性arch.py L73-L105它根据输入构造一条抛物线同时给定crown_x与crown_y设抛物线为y a*(x - x0)**2 y0代入左支座坐标解出系数a再回代校验右支座是否落在抛物线上若不满足会抛出ValueError: provided coordinates of crown and supports are not consistent with parabolic arch坐标组合与抛物线不一致。仅给定crown_x设抛物线为y a*(x - x0)**2 c分别代入左右支座得到关于(a, c)的二元方程组并求解若解不出两个独立解或a 0抛出ValueError提示可以尝试提供crown_y。求解成功后会反填crown_y。两者都未给出抛出KeyError: please provide crown_x to construct arch。从源码看__init__内部会将left_support、right_support、crown_x、crown_y全部经过sympify处理arch.py L39-L49因此这些坐标既可以是普通数值也可以是 SymPy 符号或表达式这为后续符号化求解奠定了基础。施加荷载apply_load 详解apply_load是给拱施加荷载的唯一入口arch.py L142-L246。它的参数定义如下参数类型说明orderInteger荷载的阶数-1表示集中/点荷载0表示分布荷载labelString or Symbol荷载标签不能使用A或B保留给支座使用同一标签重复施加会抛ValueErrorstartFloat集中荷载为作用点的 x 坐标分布荷载为起始位置magSympifyable荷载大小文档要求为正值endFloat仅分布荷载需要为终止位置集中荷载不传NoneangleSympifyable集中荷载向量与水平方向的夹角逆时针单位为度分布荷载不需要施加分布荷载a Arch((0, 0), (10, 0), crown_x5, crown_y5) a.apply_load(0, C, start3, end5, mag-10)分布荷载要求end不为None且大于start否则抛出KeyError(provide end greater than start)。在源码中分布荷载被记录为{start: start, end: end, f_y: mag}arch.py L210并基于Min(x, end)构造分段线性荷载函数与相应的弯矩贡献最终汇入Piecewise分段函数中。施加集中荷载a Arch((0, 0), (10, 0), crown_x5, crown_y5) a.apply_load(-1, C, start2, mag15, angle45)集中荷载必须提供angle否则抛出TypeError(please provide direction of force)。源码会先把荷载作用点投影到拱面上height self._shape_eqn.subs({x: start})再按角度分解为水平与竖直分量self._conc_loads[label] { x: start, y: height, f_x: mag*cos(rad(angle)), f_y: mag*sin(rad(angle)), mag: mag, angle: angle }arch.py L226-L228注意角度通过rad()转为弧度参与三角函数计算。施加荷载后可通过get_loads属性查看荷载记录a.get_loads # 形如{concentrated: {...}, distributed: {...}}管理荷载与结构要素移除荷载remove_load(label)按标签移除已施加的荷载arch.py L249-L298分布荷载与集中荷载分别处理并从分段函数中回退对应的荷载与弯矩贡献最后打印被移除的荷载信息a Arch((0, 0), (10, 0), crown_x5, crown_y5) a.apply_load(0, C, start3, end5, mag-10) a.remove_load(C) # 输出removed load C: {start: 3, end: 5, f_y: -10}若标签不存在抛出ValueError(label not found)。修改支撑与冠部方法作用关键规则change_support_position(left_supportNone, right_supportNone)修改支座坐标未传参的一端保持原值修改后自动重建形状方程arch.py L300-L328change_crown_position(crown_xNone, crown_yNone)修改冠部铰位置未传参默认取None并重建形状方程见 arch.py L330-L348change_support_type(left_supportNone, right_supportNone)将某端支撑改为roller滚动支座或hinge铰支座默认保持hinge传入值必须在[roller, hinge]中否则抛ValueErrorarch.py L350-L386add_member(y)在指定高度y处添加一根水平杆member/rod用于在存在滚动支座时保证结构稳定y必须介于支座高度与冠部高度之间否则抛ValueErrorarch.py L388-L400典型用法将右端改为滚动支座并添加稳定杆a Arch((0, 0), (10, 0), crown_x5, crown_y5) a.change_support_type(right_supportroller) a.add_member(0) # 在 y0 高度放置水平杆需要特别注意的是solve()中有一道硬性检查arch.py L519-L521if (self._supports[left]roller or self._supports[right]roller) and not self._member: print(member must be added if any of the supports is roller) return即只要任一端是滚动支座就必须先用add_member添加杆件否则solve()会直接返回而不做任何计算——这是三铰拱在有滚动支座时保证静定可解的结构前提。求解反应力与内力solve 方法solve()是模块的核心计算入口arch.py L445-L647完成三件事根据荷载的间断点把离散的荷载/弯矩字典组装成Piecewise分段函数_load_x_func、_load_y_func、_moment_x_func、_moment_y_func依据支座类型组合建立静力平衡方程组水平力平衡、竖向力平衡、对 A 点取矩、铰点两侧取矩用 SymPy 的solve求解支座反力R_A_x, R_A_y, R_B_x, R_B_y滚动支座场景还会解出杆件拉力T计算弯矩、剪力和轴力的符号表达式。全铰支座示例两端均为铰支座默认情形a Arch((0, 0), (10, 0), crown_x5, crown_y5) a.apply_load(0, C, start3, end5, mag-10) a.solve() a.reaction_force # {R_A_x: 8, R_A_y: 12, R_B_x: -8, R_B_y: 8}符号荷载示例mag支持符号量因此反力与内力可以表达为参数的函数——这是 SymPy 符号计算相比数值工具的核心优势from sympy import Symbol t Symbol(t) a Arch((0, 0), (16, 0), crown_x8, crown_y5) a.apply_load(0, C, start3, end5, magt) a.solve() a.reaction_force # {R_A_x: -4*t/5, R_A_y: -3*t/2, R_B_x: 4*t/5, R_B_y: -t/2} a.bending_moment_at(4) # -5*t/2支座类型组合与求解分支源码针对支撑类型组合枚举了多条求解分支arch.py L525-L629两端均滚动roller-roller先检查杆件位置self._member[2]相对两端支座高度的关系再决定采用哪组平衡方程若水平合力非零且杆高于支座抛ValueError左滚动右铰 / 右铰左滚动同样按杆件高度分三种情况高于两端、高于左端、高于右端建立含杆件拉力T的方程组两端铰支经典的 4 个方程 4 个未知数水平/竖向力平衡 对 A 点取矩 铰点右侧取矩。查询内力shear_force_at / bending_moment_at / axial_force_at三个查询方法签名一致arch.py L402-L443不传位置返回整个表达式符号公式传位置代入 x 坐标求值传dir关键字在断点处按方向取单侧极限内部使用sympy.limit用于精确读取集中荷载作用点两侧的突变值。a Arch((0, 0), (40, 0), crown_x20, crown_y12) a.apply_load(-1, C, 8, 150, angle270) a.apply_load(0, D, start20, end40, mag-4) a.solve() a.axial_force_at(7.999999999999999) # 约 149.430523405935 a.shear_force_at(7.999999999999999) # 约 64.9227473161196 a.bending_moment_at(4) # 代入 x0 求值从实现上看弯矩表达式为arch.py L634-L636self._bending_moment - (self._moment_x_func.subs(x, x0) self._moment_y_func.subs(x, x0) - solution[R_A_y]*(x0 - self._left_support[0]) solution[R_A_x]*(self._shape_eqn.subs({x: x0}) - self._left_support[1]))而轴力与剪力则通过沿拱面切线方向的坐标变换获得arch.py L638-L647angle atan(diff(self._shape_eqn, x)) # 拱面切线倾角 fx (self._load_x_func solution[R_A_x]) fy (self._load_y_func solution[R_A_y]) axial_force fx*cos(angle) fy*sin(angle) shear_force -fx*sin(angle) fy*cos(angle)即先由荷载函数与支座反力合成截面的合力分量再投影到切线/法线方向得到轴力与剪力——这解释了为什么轴力在拱结构中通常占主导而弯矩较小也正是拱能跨越长跨度减少弯矩的力学根源。可视化draw 方法solve()之后可以调用draw()获得一个 SymPy 绘图对象arch.py L649-L753图中包含拱面线、支座标记、荷载箭头与标注、以及可选的稳定杆并自动根据几何范围设置坐标轴。示例from sympy import Symbol t Symbol(t) a Arch((0, 0), (40, 0), crown_x20, crown_y12) a.apply_load(-1, C, 8, 150, angle270) a.apply_load(0, D, start20, end40, mag-4) a.apply_load(-1, E, 10, t, angle300) p a.draw() p.show()draw()标注了doctest_depends_on(modules(numpy,))说明绘图依赖 numpy源码顶部通过import_module(numpy, ...)惰性导入在分布荷载箭头采样numpy.arange与拱身填充矩形绘制中都会用到。绘制细节由三个私有方法协作完成_draw_supports()按支座类型绘制铰支座三角标记或滚动支座圆圈标记并加地面线arch.py L756-L849_draw_rectangles()绘制稳定杆与分布荷载作用范围arch.py L851-L914_draw_loads()绘制集中荷载的带箭头的标注与分布荷载的密集箭头簇arch.py L916-L999。完整工作流示例综合上述 API一次完整的分析流程如下from sympy.physics.continuum_mechanics.arch import Arch from sympy import Symbol t Symbol(t) # 荷载大小参数 # 1. 建模跨径 40矢高 12 的抛物线三铰拱 a Arch((0, 0), (40, 0), crown_x20, crown_y12) # 2. 施加荷载集中力 分布荷载 a.apply_load(-1, C, 8, 150, angle270) # (8,0) 处 150N 竖直向下 a.apply_load(0, D, start20, end40, mag-4) # 20~40 段 4 N/m 分布荷载 # 3. 求解 a.solve() # 4. 读取结果 print(a.reaction_force) # 四个支座反力分量 print(a.bending_moment_at()) # 弯矩符号表达式 print(a.axial_force_at(10)) # 某处轴力 print(a.shear_force_at(10)) # 某处剪力 # 5. 可视化 a.draw().show()测试验证与注意事项模块行为由 sympy/physics/continuum_mechanics/tests/test_arch.py 中的测试用例约束可作为使用对照test_arch_init验证构造默认状态、get_shape_eqn解析结果、change_support_type与add_member的组合使用test_arch_support集中 分布荷载下反力数值如R_A_y 140、R_B_x -83.333...与预期一致test_arch_member右端滚动支座 稳定杆 三个竖直集中荷载下的反力验证test_symbol_magnitude符号荷载t下反力与弯矩的符号表达式验证test_forces轴力/剪力的数值验证。使用中需留意以下限制与约定形状限制模块目前仅支持二维抛物线拱且必须提供crown_x支座与冠部坐标必须落在同一条抛物线上否则抛ValueError。标签保留字荷载标签不能用A、B支座用且同一标签不能重复施加。滚动支座必须配杆任一端为roller时必须先add_member否则solve()静默返回仅打印提示。集中荷载必须给角度order-1时angle为必填方向角以度为单位、逆时针为正。依赖draw()需要 numpy其余计算为纯 SymPy 符号运算。更多相关结构分析工具可参考同目录下的 beam.py、cable.py、truss.py以及对应的文档页 beam.rst、cable.rst、truss.rst。【免费下载链接】sympyA computer algebra system written in pure Python项目地址: https://gitcode.com/GitHub_Trending/sy/sympy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考