
干了这么多年岩土数值仿真我最怕的不是建模不是调参数而是算完之后的最后一步怎么把弯矩、轴力、剪力从FLAC3D里干干净净地弄出来画成能放进报告里的图。实体单元想看应力右键选contour就完事了可一旦碰到桩单元、梁单元这些结构单元内置云图基本帮不上忙很多人只能对着命令行发呆最后从节点列表里手工抄数据。FLAC3D里常说的“云图”本质上是把某个标量在空间上的分布用颜色渲染出来这和气象上用卫星云图显示云顶温度、图像处理里把深度图转成点云后再着色底层思路完全一致——数值计算产生了海量离散数据人眼要识别规律必须靠可视化。这篇内容就围绕桩单元与梁单元的内力云图显示和包络线提取展开把我实际摸索过的FISH脚本、数据导出流程、云图绘制方案、多工况包络线做法连同踩过的坑一并整理出来希望能帮到正在被FLAC3D结构单元后处理折磨的研究生和工程师。1. 为什么桩/梁单元的内力云图是绕不开的坎1.1 结构单元与实体单元的显示逻辑完全不同FLAC3D把计算对象分成两大类一类是实体区域用zone表示每个zone有应力、应变这些高斯点或节点变量另一类是结构单元比如pile、beam、cable、liner它们是嵌在实体网格里的线单元/面单元。对实体区域PLOT里直接选contour of z-extra或者选stress就能看到彩色云图因为应力在每个zone上就是有明确定义的物理量。但桩单元和梁单元不一样。它们是带方向的杆系单元内力轴力、剪力、弯矩、扭矩是定义在杆件局部坐标系下的。轴力沿着杆轴线剪力和弯矩分别在横向两个方向。FLAC3D默认的plot菜单里结构单元通常只显示几何形状和变形并不会像实体单元那样把内力渲染成连续云图。就算新版本增加了部分结构单元变量选项那也是固定变量、固定位置想按自己的工程习惯整理数据或者做多工况包络线内置功能远远不够。所以要做内力云图思路必须绕一下先用FISH把结构节点的力和力矩提取出来在局部坐标系下换算成轴力N、剪力V、弯矩M然后要么写回zone的extra变量里再做contour显示要么导出成文本文件交给Origin、MATLAB、Python重新绘图。这条路线绕但能完全控制输出格式和内容。1.2 内力云图的真实工程用途我最早做这个需求是因为基坑支护计算要出支撑轴力包络图。基坑里内支撑用的是梁单元围护桩用的是桩单元设计院要的成果不只是“最大轴力是多少”而是沿着支撑长度或桩身深度的完整分布曲线而且必须覆盖开挖全过程的多个工况。桩身弯矩分布用来判断正负弯矩极值点位置是抗弯配筋的核心依据支撑轴力包络用来确定支撑截面和预加轴力梁单元剪力分布用于校核节点连接和抗剪构造。手里如果只有最大值的云图没有沿深度的包络线设计参数基本没法落地。所以“云图”只是第一步真正要的是能指导设计的内力包络。1.3 包络线为什么不能指望FLAC3D一键生成有一次我图省事想看看FLAC3D有没有内置的包络功能翻遍了命令手册也没找到。本质上包络线是一个后处理统计概念不是数值计算本身的结果。它的定义是在若干个计算工况比如开挖至-5m、-8m、-12m或者不同水位条件、不同荷载组合下对同一位置的内力取最大值和最小值逐点连接成两条线。FLAC3D每次只能算一个工况算完后模型状态可以保存或重置。要把多个工况的数据汇总到同一个坐标系里画出包络线必须自己做数据管理。这个过程很容易出错尤其是网格节点顺序、工况命名、数据对齐这些问题稍不留神包络线就画成了乱麻。后文我会给出一套能反复用的处理流程。2. 核心细节解析与实操要点2.1 节点力、节点力矩与单元内力到底什么关系很多人以为FLAC3D的pile单元节点上直接存了轴力、弯矩实际上节点存储的是节点力矢量force和节点力矩矢量moment。这两个量是结构单元在节点处平衡得到的等效节点力包含了该节点两侧单元传给它的内力以及外部荷载的贡献。想得到单元的内力一种可行且工程上常用的方法是取一个结构单元得到它的两个端节点编号计算单元轴线方向的单位向量然后把节点力矢量分别投影到轴向和横向得到轴力和剪力节点力矩矢量投影到横向得到弯矩。轴力的正负需要特别小心不同版本FLAC3D的符号约定有差异建议先用一个悬臂梁或单轴压缩模型做验证确认之后再用到实际工程上。2.2 FISH接口新旧版本差异必须提前确认我最早用的是FLAC3D 5.0老版本里结构单元相关的命令是sel比如sel pile list、sel node listFISH函数也比较直白。后来换成FLAC3D 6.0和7.0命令风格大改结构单元从sel改成了structFISH函数的命名也变成了struct.pile.list、struct.node.pos这种风格。如果你直接粘贴网上的旧脚本十有八九会报错。下面这段FISH代码以FLAC3D 6.0以上的风格为例提取桩单元节点位置、节点力和节点力矩并计算单元轴向和初步的轴力分量。不同版本请按实际函数名微调。fish define get_pile_axial local pids struct.pile.list loop foreach p pids local n1 struct.pile.node1(p) local n2 struct.pile.node2(p) local p1 struct.node.pos(n1) local p2 struct.node.pos(n2) local axis p2 - p1 axis math.normalize(axis) local f1 struct.node.force(n1) local f2 struct.node.force(n2) ; 注意此处按“以节点平衡力方向反推杆端内力”处理 local N1 -math.dot(f1, axis) local N2 math.dot(f2, axis) io.out(string(p) string(N1) string(N2)) endloop end2.3 单位、坐标系与符号约定三个大坑FLAC3D本身没有内建单位长度、力、应力都用一套自定义单位。很多新手在模型里用mm或cm提取出来的节点力是N但弯矩单位就变成N·mm出图时数字大得吓人第一反应是模型算错了。建议建模前统一单位推荐用m和N或kN搭配弯矩单位就是N·m或kN·m。另一个坑是局部坐标系。桩或梁单元的轴向可能是空间任意方向的提取节点力后不能直接看某一个分量说“这就是轴力”必须算方向余弦然后投影。基坑围护桩一般是竖直的轴向沿z内支撑可能是水平斜撑轴向与x、y都有夹角不投影就全错了。符号约定方面FLAC3D默认以受拉为正也就是说桩身轴力如果是正数表示单元受拉。但土建结构设计习惯常常把受压为正、受拉为负两者转换时要统一报告中最好注明符号规则不然看图的人会一头雾水。3. 实操过程与核心环节实现3.1 案例一单桩水平受荷模型的内力提取与曲线绘制先给一个最简单的验证场景。一根桩长10m直径0.8m顶面作用水平集中荷载300kN。桩单元划分成10段每段1m桩顶节点和桩底节点固定约束。材料参数略。计算完成后我提取各节点处沿桩身方向的弯矩方法和前面FISH脚本类似。提取后得到一组离散点节点编号0到10对应深度0到10m。把弯矩作为纵轴、深度作为横轴就能画出桩身弯矩分布曲线。实测下来桩顶处的弯矩接近300kN×1m300kN·m如果桩顶无约束往下逐渐变化形状和弹性理论解大致吻合。这个简单案例建议每个人在正式项目前都跑一遍主要目的是验证自己的FISH提取逻辑和符号约定是否正确。3.2 案例二基坑排桩加内支撑多工况包络线基坑开挖模型排桩用pile单元模拟水平内支撑用beam单元模拟。分析工况假设有三个开挖至-5m、-8m、-12m支撑依次加设。每个工况算完后调用一个FISH函数把每根桩每个节点的深度、弯矩、轴力、剪力写入CSV文件文件名带上工况标识。fish define export_pile_force(file_name) local pids struct.pile.list local fp file.open(file_name, write) local n1 0 local n2 0 local p1 vector(0,0,0) local p2 vector(0,0,0) local axis vector(0,0,1) local f1 vector(0,0,0) local f2 vector(0,0,0) local depth 0.0 local N 0.0 loop foreach p pids n1 struct.pile.node1(p) n2 struct.pile.node2(p) p1 struct.node.pos(n1) p2 struct.node.pos(n2) axis p2 - p1 axis math.normalize(axis) f1 struct.node.force(n1) f2 struct.node.force(n2) N -math.dot(f1, axis) depth p1.z file.write(fp, string(depth) , string(N) , string(f1.x) , string(f1.y)) endloop file.close(fp) end这里第三行代码用于打开文件后面写深度、轴力和节点力分量。真实项目中你还需要输出弯矩节点力矩用struct.node.moment取同样投影到垂直于轴向的两个方向。重点是把深度信息一起写进去否则后面做包络线没法对齐位置。三个工况跑完后手上有了三个CSV每个文件里的深度点是同一组网格位置这给后处理省了很多麻烦。用Python的pandas读进来按深度分组对每一深度点求弯矩的最大值和最小值就能得到包络上线和包络下线。import pandas as pd import matplotlib.pyplot as plt df_list [] for case in [s5, s8, s12]: df pd.read_csv(fpile_{case}.csv, names[depth, N, fx, fy]) df[case] case df_list.append(df) df_all pd.concat(df_list, ignore_indexTrue) df_env df_all.groupby(depth)[N].agg([max, min]).reset_index() plt.figure(figsize(6, 8)) plt.plot(df_env[max], df_env[depth], labelmax) plt.plot(df_env[min], df_env[depth], labelmin) plt.xlabel(Axial Force (kN)) plt.ylabel(Depth (m)) plt.legend() plt.gca().invert_yaxis() plt.grid(True) plt.show()这是最朴素的包络线画法。如果多个工况的桩单元分段不一致或者网格节点不在同一深度就不能直接groupby需要先按深度插值到统一网格。建议在建模阶段就把桩单元分段设定为统一方案开头一个网格所有工况都复用能省掉后续大量插值工作。3.3 二维云图展示把“深度-桩号-内力”变成彩色图工程报告里的云图不完全等同于软件里的三维彩图。对排桩这类场景我更推荐用二维热力图横轴是桩号或桩位置纵轴是深度颜色表示弯矩或轴力。这样一整排桩的内力分布一目了然也方便标注正负弯矩区。数据准备方法把各桩的提取结果拼成一个二维数组行对应深度列对应桩号。用matplotlib的pcolormesh或imshow可以直接出图。如果相邻桩位置不整齐可以先在横轴方向插值到统一间距。这种图和FLAC3D自带的三维contour相比信息密度更高打印到A4图纸上也清晰。如果想要三维模型空间里的云图效果可以把提取到的内力值写入zone额外的extra变量再给这些zone设成很小的刚度或单独显示。这样做不是为了参与计算纯粹是为了借用FLAC3D的contour渲染能力。需要注意写extra的网格范围要刚好包住桩单元否则云图范围会超出结构范围看起来很奇怪。这个方法我以前试过能出效果但操作繁琐模型大了以后切换显示也很卡所以现在多数情况直接用外部绘图。3.4 绘制云图与包络线的方案选型方案适合场景主要优点主要缺点FLAC3D plot table快速检查单根桩结果不用导出随手看多条曲线混放不直观做不了包络Excel/Origin报告曲线、包络线操作轻易上手批量处理几十根桩时很繁琐Python matplotlib批量处理、二维热力云图脚本化可复现需要会写PythonMATLAB研究分析、复杂绘图插值工具箱齐全授权成本高Tecplot三维云图可视化专业数据格式转换麻烦我的经验是验算阶段用FLAC3D自带table快速看趋势提交成果阶段用Python批量生成曲线、包络线和热力云图。Excel适合数据量小、只需要一两根桩的情况一旦数据量上来复制粘贴容易出错还是脚本靠谱。4. 常见问题与排查技巧实录4.1 为什么提取出的节点力全是零大概率是计算还没收敛或者节点选择范围不对。FLAC3D结构单元的节点力只有在求解结束后才能真正反映内力如果你在model solve之前就调用FISH函数节点力自然是零。另外检查struct.node.force返回的是矢量还是标量不同版本返回类型有区别用math.dot之前建议先打印出来看一眼。4.2 轴力正负号和设计习惯不一致FLAC3D默认受拉为正、受压为负但土建结构设计里很多时候习惯把受压作为正。这种问题不是计算错误是符号约定不统一。建议在FISH导出阶段就完成转换比如在N1的公式里加一个负号并且在CSV表头里注明“压为正”。不要等到画图时再翻转那样很容易漏掉某根构件。4.3 包络线出现毛刺或异常跳变出现过一次包络线在某个深度点突然出现很大峰值排查后发现是某一工况在该深度处恰好有节点力集中和相邻工况的数据点不是同一个网格位置导致插值误差。解决办法有两个一是所有工况建模时保证桩单元的节点深度完全一致二是在做包络前把所有工况的桩单元划分加密到0.5m或更小减小离散位置误差。加密桩单元分段对计算结果影响不大但对包络线光滑度有明显改善。4.4 梁单元和桩单元脚本不能通用乍看都是线单元写法很接近但FISH函数名不同struct.pile.list和struct.beam.list是两个独立函数。另外梁单元可能有节点释放、端部铰接等情况铰接端节点力矩应为零如果提取出来非零要检查单元连接是否正确。桩单元因为有桩土耦合弹簧节点内力中会包含土体相互作用项提取时不能只拿其中一个节点力当作全单元内力。4.5 新旧版本脚本兼容性问题汇总FLAC3D版本结构单元命令风格常见FISH函数5.0sel pile / sel nodesel pile list、sel node pos6.0struct.pile / struct.nodestruct.pile.list、struct.node.pos7.0同6.0部分对象接口增强struct.node.force、struct.node.moment如果你用的是5.0把struct换成sel把struct.pile.list换成sel pile list基本能对上。但注意5.0里节点位置函数不是struct.node.pos而是类似nd_pos或sel node pos返回的张量建议在命令行里help一遍再写脚本。我踩过这个坑耗了一整天查一个函数名。4.6 云图颜色范围对不齐多工况出图时如果每个工况单独用imshow默认颜色范围是各自数据的最小到最大导致两幅图对比时色标尺度不一致看起来很误导。建议在出图前统一所有工况的vmin和vmax比如统一取所有工况弯矩的全局最小值和最大值。这一点很基础但特别容易被忽略。最后再分享一个小技巧我自己在多个项目里反复用这套流程后总结了两个习惯。第一个是每次写FISH提取脚本后先跑一个带理论解的简单模型比如单桩水平受荷确认提取的弯矩和理论解误差在10%以内再上实际工程。这个验证过程十分钟左右但能省掉后面好几天返工。第二个是CSV文件命名严格带工况标记和时间戳比如pile_s8m_v2.csv千万别用pile1、pile2这种名字否则工况一多包络线数据容易搞混。这套“FISH提取-脚本制图-包络线汇总”的流程从FLAC3D 5.0到7.0我都用过基本思路没变过。结构单元内力显示这种问题核心不在于三维云图多炫而在于数据提取准确、包络整理清晰。希望这篇文章能让你的结构单元后处理不再卡壳把精力放回到工程问题本身。