简介:这份资源面向从事岩土工程数值模拟的技术人员与科研工作者,聚焦FLAC3D实体单元无法直接输出弯矩、轴力的痛点,系统讲解基于应力积分的截面内力提取方法。内容涵盖FISH函数实现思路、隧道初期支护与地铁支护桩等实战案例,并延伸至单位换算、截面选取、网格划分等易错细节,以及结果验证与精度校核的实用技巧。资源包为1个PDF文件,约104KB,篇幅紧凑,便于快速查阅与对照练习。目前已有135人学习。读者可从中获得从原理到代码落地的完整路径,理解如何筛选目标单元组、定位目标截面并累计轴力与弯矩,同时借助案例数据观察支护结构受力的动态变化,为论文验证与工程分析提供可靠参考。
1. 实体单元里没有弯矩,为什么还要提取弯矩
做岩土和地下结构数值分析的人,迟早会撞上这个需求:用 FLAC3D 建了隧道衬砌、抗滑桩、地下连续墙,模型跑完了,位移云图也看了,可一到写报告、对规范、评配筋,甲方或评审就问一句——弯矩和轴力是多少。问题在于,FLAC3D 的实体单元(zone)本质是连续介质单元,它的基本输出是应力张量,压根没有梁单元那种现成的弯矩、剪力、轴力。你打开 history 或 zone 的应力分量,看到的永远是 sxx、syy、szz、sxy 这些,弯矩轴力得自己从应力分布里积分出来。
这就是「FLAC3D实体单元弯矩轴力提取技术」要解决的事:把实体单元截面上的正应力沿厚度方向做一次积分,得到轴力;再让正应力乘上到中性轴的距离做一次积分,得到弯矩。听起来是材料力学里最基础的那套公式,但真到 FLAC3D 里落地,截面怎么切、应力怎么取、中性轴怎么定、单位怎么统一,每一步都能让人翻车。这篇笔记面向已经会用 FLAC3D 建模、但卡在「内力提取」这一步的从业者,也适合刚接手衬砌或桩基内力后处理的新手。下面从原理、截面定义、FISH 脚本实现、避坑到验证,一步步讲透。
2. 从应力到内力:截面应力积分法的原理与选型
2.1 为什么实体单元必须走积分这条路
FLAC3D 里的结构单元(beam、pile、liner)自带弯矩轴力输出,这是很多人第一反应会想到的替代方案。但结构单元和实体单元是两套力学体系:结构单元是简化的梁/壳理论,和实体网格之间靠 link 连接,连接刚度、滑移、脱空这些行为很难和实体完全一致。如果你的模型主体是实体单元(比如衬砌用实体建、围岩用实体建),硬塞一根 beam 进去,得到的弯矩反映的是那根梁的受力,不是实体截面的真实内力分布。
截面应力积分法的逻辑很直接:在你要考察的位置切一个截面,把这个截面穿过的所有实体单元的应力取出来,沿截面法向做面积分。轴力 N 是正应力对面积的积分,弯矩 M 是正应力对中性轴取矩再积分。对矩形截面衬砌,如果应力沿厚度近似线性分布,还能退化成用上下边缘应力算弯矩的简化公式。这条路的好处是不依赖任何结构单元,纯后处理,模型怎么建都不影响;代价是截面定义和积分精度要自己控制。
常见做法有两种:一是沿截面把单元应力按面积加权求和,适合网格较粗、应力分布平缓的情况;二是先插值到截面上的高斯点或网格点,再积分,精度更高但实现复杂。我一般先用第一种跑通,看结果量级对不对,再决定要不要上插值。
2.2 截面定义:切在哪、切多宽、法向朝哪
截面定义是整件事的地基。切错了位置,后面积分再精确也是错的。三个要素必须明确:截面位置、截面范围、截面法向。
截面位置通常选在你要评估内力的关键断面,比如隧道拱顶、拱腰、墙脚,或者桩身每隔几米一个断面。截面范围要覆盖整个受力构件厚度,比如衬砌厚度 0.5 m,那截面就要从内表面切到外表面,不能只切一半。截面法向决定了你算的是哪个方向的弯矩——沿隧道纵向切,得到的是环向弯矩;沿横向切,得到的是纵向弯矩。
在 FLAC3D 里,截面不是几何实体,而是你人为定义的一组单元集合。常用做法是用 FISH 遍历所有 zone,判断单元形心是否落在截面平面附近的一个薄层内,把满足条件的单元收集起来。薄层厚度一般取略大于单元尺寸,保证截面至少穿过一层单元,又不至于把邻近断面的单元也卷进来。
提示:截面薄层厚度如果取成单元尺寸的一半,容易出现某些位置一个单元都没选中,积分结果直接为零。建议先跑一遍统计选中单元数量,再调厚度。
2.3 中性轴的确定:几何中性轴还是力学中性轴
弯矩的定义依赖中性轴位置。对均质矩形截面,中性轴在几何中心,直接取厚度一半就行。但衬砌、桩基往往不是均质——钢筋混凝土、钢拱架、围岩共同作用,弹性模量沿厚度变化,力学中性轴会偏离几何中心。这时候如果还用几何中心,弯矩会有系统性偏差。
工程上常见的处理有两种。一是按弹性模量加权求中性轴位置,公式是 y_n = Σ(E_i·A_i·y_i) / Σ(E_i·A_i),把截面离散成若干条带,每条带用对应材料的模量。二是直接用上下边缘应力反算,假设应力线性分布,中性轴位置由应力零点确定。前者适合材料分区明确的情况,后者适合你已经拿到应力分布、想快速估算的情况。
我一般会两种都算一遍做交叉验证。如果两者差得不多,说明截面接近均质,用几何中心也能接受;如果差得多,就得老老实实按模量加权,否则弯矩可能差出百分之二三十。
2.4 单位与符号:最容易被忽略的一致性陷阱
FLAC3D 本身没有单位制,你输入什么单位,输出就是什么单位。常见翻车场景是:几何用米、应力用帕、力却按千牛去理解,最后弯矩数量级错三个零。做积分前,先把整套单位理一遍——长度 m、应力 Pa、力 N、弯矩 N·m,需要千牛米再统一换算。
符号约定同样要固定。轴力拉为正还是压为正,弯矩使哪一侧受拉为正,这些在报告里要写清楚,否则同一组数据不同人解读会打架。我的习惯是:轴力以压为正(衬砌主要受压),弯矩以截面内侧受拉为正,并在脚本注释里写死,避免后面自己都记混。
3. 用 FISH 把截面应力积分成弯矩轴力
3.1 收集截面单元:遍历与筛选
第一步是把落在截面薄层里的单元找出来。下面这段 FISH 假设截面是沿 y 方向的一个竖直平面,位置在 x = x_sec,薄层半厚 tol。实际用的时候把坐标判断换成你的截面方向即可。
; 定义截面参数 def set_section x_sec = 5.0 ; 截面所在的 x 坐标 tol = 0.15 ; 薄层半厚,略大于单元尺寸 n_zone = 0 local zp = zone_head loop while zp # null ; 取单元形心 local cx = z_x(zp) ; 判断形心是否落在截面薄层内 if math.abs(cx - x_sec) < tol then n_zone = n_zone + 1 ; 把选中的单元指针存进数组,供后续积分用 sec_zone(n_zone) = zp endif zp = z_next(zp) endloop io.out('选中单元数量: ' + string(n_zone)) end这段逻辑的关键在 tol 的取值。太小会漏单元,太大会把邻近断面的单元也拉进来,导致积分截面变厚、弯矩偏大。判断用形心而不是节点,是因为形心能代表单元的平均位置,节点判断会把跨截面的单元重复计入。跑完先看输出的单元数量,如果和你预估的截面穿过单元数差太多,就回去调 tol。
3.2 提取应力并沿厚度积分
拿到单元集合后,逐个取应力,按单元面积加权,再对中性轴取矩。下面这段接着上面的数组做积分,假设截面法向是 x,厚度方向是 z,中性轴位置 z_na。
def integrate_section N = 0.0 ; 轴力累加 M = 0.0 ; 弯矩累加 A_total = 0.0 ; 总面积,用于校核 loop local i (1, n_zone) local zp = sec_zone(i) ; 单元体积与面积:这里用体积除以厚度近似面积 local vol = z_vol(zp) local area = vol / z_size(zp,3) ; 沿 z 方向的尺寸 ; 取 x 方向正应力(截面法向应力) local sx = z_sxx(zp) ; 单元形心到中性轴的距离 local dz = z_z(zp) - z_na ; 轴力:应力乘面积 N = N + sx * area ; 弯矩:应力乘面积再乘力臂 M = M + sx * area * dz A_total = A_total + area endloop io.out('轴力 N = ' + string(N)) io.out('弯矩 M = ' + string(M)) io.out('校核总面积 = ' + string(A_total)) end逻辑说明:z_sxx 取的是单元形心处的 x 向正应力,这是截面法向应力,正是产生轴力和弯矩的分量。area 用体积除以厚度方向尺寸近似,对规则六面体单元足够准;如果是四面体或退化单元,面积要按实际截面投影算。dz 是力臂,中性轴位置 z_na 需要你按 2.3 的方法先确定。A_total 是校核量,应该接近构件真实截面面积,差太多说明单元筛选有问题。
参数说明:z_na 是中性轴 z 坐标,均质截面取厚度中心;sx 的符号决定 N 和 M 的符号,务必和你的符号约定一致。如果截面法向不是 x,把 z_sxx 换成对应的应力分量,dz 换成对应方向的力臂。
3.3 用上下边缘应力做快速校核
积分结果出来后,别急着信。用上下边缘应力反算一个弯矩做交叉校核,是最省事的验证手段。对矩形截面,如果应力线性分布,弯矩约等于 (σ_top - σ_bot) / 2 × 截面模量。
def check_by_edge ; 取截面上边缘和下边缘单元的应力 local s_top = 0.0 local s_bot = 0.0 local z_top = -1.0e20 local z_bot = 1.0e20 loop local i (1, n_zone) local zp = sec_zone(i) local zc = z_z(zp) if zc > z_top then z_top = zc s_top = z_sxx(zp) endif if zc < z_bot then z_bot = zc s_bot = z_sxx(zp) endif endloop ; 矩形截面模量 W = b*h^2/6,b 取单位宽度 local h = z_top - z_bot local W = 1.0 * h * h / 6.0 local M_edge = (s_top - s_bot) / 2.0 * W io.out('边缘法弯矩校核 M = ' + string(M_edge)) end这段的作用是给你一个量级参照。如果积分弯矩和边缘法弯矩差在 10% 以内,基本可以放心;差得离谱,先查单元筛选和中性轴,再查应力符号。边缘法本身假设线性分布,对非线性应力会偏,所以它只做校核,不做最终结果。
3.4 把结果写进表格,方便批量断面
实际项目往往要提取几十个断面的内力,一个个手跑不现实。把截面位置做成循环,结果写进 table,最后统一导出。
def batch_section local xs(5) = array(2.0, 4.0, 6.0, 8.0, 10.0) loop local k (1,5) x_sec = xs(k) set_section integrate_section ; 把结果存进 table,第一列断面号,第二列轴力,第三列弯矩 table.x(k,1) = x_sec table.x(k,2) = N table.x(k,3) = M endloop ; 导出为文本,供 Excel 后处理 table.x('export','section_force.txt') end批量跑的时候注意每次循环都要重置 n_zone 和数组,否则上一断面的单元会残留。table 导出后可以直接进 Excel 画内力包络图,这一步对写报告特别省事。
4. 避坑与排查:弯矩轴力提取的五个血泪教训
4.1 现象:弯矩数量级明显偏大或偏小
原因:单位不统一是最常见元凶。几何用米、应力用兆帕,算出来的力是兆牛,弯矩是兆牛米,如果你按千牛米读,就大了三个数量级。另一个原因是面积算错,把体积当面积用了。
解决:积分前把所有输入量列一张单位表,长度、应力、力、弯矩逐项对齐。面积一定用体积除以厚度方向尺寸,或者直接用单元截面投影面积,别拿体积凑。
4.2 现象:同一断面不同时刻弯矩跳变剧烈
原因:截面薄层选中的单元数量在时间步之间发生变化,某个单元时进时出,积分截面忽厚忽薄。这在动力分析或大变形分析里尤其明显。
解决:把截面单元集合在计算开始前固定下来,整个时程都用同一组单元,不要每步重新筛选。如果单元确实会移动出截面,说明截面定义本身不合理,换位置或加厚薄层。
4.3 现象:轴力合理但弯矩接近零
原因:中性轴位置取错,或者力臂 dz 算成了零。常见于把中性轴取在截面形心,但代码里 z_z 取的是全局坐标,两者没对齐。
解决:打印几个单元的 z_z 和 z_na,看差值是否合理。中性轴是相对截面厚度的局部量,别和全局坐标混用。均质截面先确认厚度中心坐标,再代入。
4.4 现象:积分结果和结构单元结果对不上
原因:实体单元和结构单元的力学假设不同,link 连接刚度、滑移都会造成差异。如果实体截面和结构单元不在同一位置,差异更大。
解决:不要指望两者完全一致,差 10% 到 20% 属正常。以实体积分为准,结构单元结果只做趋势参照。真要对比,把结构单元放在实体截面同一位置,并检查 link 参数。
4.5 现象:应力符号混乱,拉压分不清
原因:FLAC3D 应力符号约定和材料力学不同,压应力在某些输出里是负的,加上截面法向定义不一致,符号很容易乱。
解决:在脚本里固定一套符号约定,注释写死。取应力后先判断符号是否符合预期,必要时统一乘 -1。报告里明确写清拉压正方向,别让读的人猜。
5. 进阶:让内力提取经得起评审的验证习惯
走到这里,脚本能跑、结果能出,但能不能拿去评审,取决于你有没有验证习惯。我这些年养成的做法是:任何一个断面的内力,至少用两种独立方法算一遍,对不上就查,绝不单点采信。
第一种是截面应力积分,就是前面讲的主方法。第二种是边缘应力反算,用上下边缘应力加截面模量快速估。第三种,如果模型里有对应的结构单元,拿它的弯矩做趋势对照。三者量级一致、趋势一致,才敢往报告里写。下面这张表是我常用的验证对照模板,每个断面填一行,一眼就能看出哪个断面异常。
| 断面位置 | 积分轴力 | 积分弯矩 | 边缘法弯矩 | 结构单元弯矩 | 偏差是否可接受 |
|---|---|---|---|---|---|
| 拱顶 | 按实填 | 按实填 | 按实填 | 按实填 | 是/否 |
| 拱腰 | 按实填 | 按实填 | 按实填 | 按实填 | 是/否 |
| 墙脚 | 按实填 | 按实填 | 按实填 | 按实填 | 是/否 |
除了数值对照,还有两个习惯值得坚持。一是把截面位置、薄层厚度、中性轴、单位制这些参数写进脚本头部注释,换个人接手也能看懂。二是每次改模型或改网格后,重新跑一遍单元筛选统计,确认截面穿过的单元数量没有突变——网格一变,原来的薄层厚度可能就不合适了。
再进阶一点,可以把内力提取做成自动后处理:计算结束后自动遍历预设断面列表,输出内力包络图和极值表。这样每次改参数重算,不用手动重复操作,也减少人为选错断面的概率。我一般会把断面列表和材料分区参数放在单独的数据文件里,脚本读文件、跑积分、出表,整个流程可复现。
最后说个我自己的教训。早年做一个衬砌内力提取,积分弯矩和边缘法差了将近一倍,我图省事直接用了积分结果,报告交上去被评审一眼看出问题——中性轴取的是几何中心,但截面里有钢拱架,力学中性轴偏了。返工重算不说,还耽误了进度。从那以后,我养成了一个死习惯:任何内力结果,先过一遍边缘法校核,对不上就查中性轴和单元筛选,绝不跳过。这个习惯帮我省下的返工时间,远比多花的那点校核时间多。希望帮到你。
本文还有配套的精品资源,点击获取