资讯动态

FLAC弹性应变能分析二次开发:从FISH脚本到自定义本构实现

发布时间:2026/10/14 14:36:31 来源:尧图企业网站定制
做岩土数值分析的人应该都有体会绝大多数时候我们盯着应力、位移、塑性区说话一到冲击地压、岩爆倾向评价、开采扰动范围分析这类问题光看应力大小往往说不清楚因为同样大小的应力在不同弹模、不同围压下对系统的影响完全不是一回事。这时候能量视角就特别有用——它把应力、应变、体积变化、畸变程度统一到同一个量纲里回答了“系统到底积聚了多少可释放的弹性能”这个关键问题。Flac系列的二次开发圈子这几年讨论弹性应变能分析的案例明显变多但很多朋友卡在第一步FLAC本身并没有一条现成命令能直接给你输出应变能密度云图。所以这篇文章我就把这个方向彻底拆开讲从原理到FISH脚本实现再到自定义本构层面的能量积分把能落地的东西一次写清楚。先说清楚这篇内容适合谁。如果你在用FLAC2D/FLAC3D做岩土、采矿、地下工程数值模拟想算弹性能空间分布、统计塑性耗散能、做能量时程追踪或者想在自己的本构模型里记录能量演化这篇文章就是给你写的。不要求你有多深的编程底子FISH路线的部分我尽量写成可以直接抄的脚本自定义本构那部分会更接近开发者的视角属于进阶内容但也会把框架讲明白。1. 弹性应变能分析到底解决什么问题FLAC原生为什么搞不定1.1 能量分析在岩土工程里的典型应用场景先聊为什么要做能量分析。应力位移分析相当于在问“哪儿受力大、哪儿变形多”能量分析则在问“哪儿攒了劲儿、这股劲儿放出来会造成什么后果”。我见过的最典型的几个场景第一是深部开采的岩爆倾向性评价。采掘空间开挖后围岩应力重新分布局部区域会形成高弹性能积聚区一旦能量密度超过临界值扰动触发下弹性应变能突然释放就成了岩爆。单纯看应力集中系数很多经验判据其实已经够用但要把开挖顺序、支护时机、卸压措施的效果对比清楚能量指标往往比应力指标更稳定、更直观。第二是冲击地压的监测预警反演。现场微震监测给出了能量释放量数值模型如果能算出同样的震源区域能量积聚速率两者就能互相印证这是用数值手段做反演的重要基础。第三是边坡和隧道的失稳前兆研究。边坡临滑前往往伴随能量积聚区向坡脚转移隧洞破裂区扩展也对应弹性能密度高值区向深部迁移做这些分析都离不开能量云图。再往细里说能量分析还经常被用来量化支护效果。锚杆、锚索、衬砌有没有真正起到“消耗能量”的作用看应力变化有时不太明显但看塑性耗散能和弹性能的相对比例变化就很清晰。比如某地下工程方案对比不支护时围岩弹性能在洞周高度集中加柔性支护后弹性能峰值降低、高能区向深部推移这些结论用能量云图呈现出来评审专家一眼就能看懂比贴一排应力曲线更有说服力。1.2 FLAC原生到底缺了什么FLAC的内置功能里应力、应变、塑性区指示器都有你甚至可以直接查看每个zone的应力张量分量和应变增量分量。但是翻遍命令手册你会发现它没有“应变能密度”这个现成的单元属性也没有全模型能量统计的历史记录变量。为什么这么基础的东西没有内置我理解有两方面原因。一是能量计算路径和本构模型强相关。对线弹性材料弹性能密度有简单的封闭表达式但摩尔库伦、应变软化、霍克布朗这类弹塑性模型进入塑性后弹性能、塑性耗散能、塑性功三者怎么切分不同本构的理论框架不一样软件很难给一个普适的输出。二是能量统计的物理边界问题。数值模型中能量不仅存在于单元应变能里还包括动能、阻尼耗散、接触界面摩擦耗散离散元更明显FLAC作为连续介质程序以力学求解为主不主动维护系统能量账本是合理的。所以“计算弹性应变能”这个需求本质上必须靠二次开发来补。二次开发干的活说白了就是在软件原有求解流程上挂一个“能量账本”每个时步把每个单元的弹性应变能增量算出来再累加、分区、画云图。这也是这篇文章最核心的出发点。1.3 二次开发要实现的“能量账本”长什么样从功能角度一个完整的能量分析二次开发应该有四层能力。第一层单元尺度每个zone每个时步能算出一个弹性应变能密度标量可用于云图显示。第二层全局尺度全模型每个时步的总弹性能能被累加出来形成能量时程曲线。第三层分区尺度把模型按组或者按范围切块分别统计各区域的能量积聚和释放用于对比分析。第四层耗能拆分在塑性区把塑性耗散能从弹性能里剥离开这样你就知道哪些单元还在“储存能量”哪些单元已经“泄掉能量”。上面这四层FISH脚本能实现前三层第四层则需要进入自定义本构里实现。后面我会分两条路线详细讲。2. 两条技术路线怎么选FISH脚本和自定义本构模型2.1 路线一FISH脚本做后处理式能量计算FISH是FLAC内置的脚本语言可以直接访问模型对象、读取计算过程中的应力应变、控制求解流程。做弹性应变能分析最直接的办法就是用FISH写一个函数在计算过程中周期性调用遍历所有zone根据当前应力状态计算应变能密度并保存到zone的extr变量里。这条路线的本质是“后处理式”模型的本构关系完全不变能量是按弹性理论公式从当前应力状态反推出来的。这条路线的优点非常明显门槛低、不动核心计算、调试快。你不需要重新编译任何东西在FLAC的命令流里直接跑FISH脚本就行。对绝大多数工程分析场景比如画能量密度云图、统计某个区域的能量积聚量这个方案完全够用。缺点也需要说清楚它默认单元处于弹性加卸载状态一旦单元进入显著塑性流动公式算出来的“弹性能密度”就不严格等于真正存储在弹性应变里的那部分能量因为它没有把塑性耗散的历史影响全部考虑进去。好在实际工程分析里我们重点关心的往往就是弹性区和微塑性区的高能量积聚部位这部分用弹性公式是合理的。如果模型里大量单元进入严重屈服比如模拟垮落带、破碎带那FISH路线算出来的能量密度可信度就要打折扣这时候该考虑第二条路线。2.2 路线二自定义本构模型内嵌能量积分第二条路线是开发用户自定义本构模型在C层面把弹性应变能、塑性耗散能的积分直接做进本构计算里。FLAC系列程序提供了一套完整的本构开发接口开发者用VC编写新的本构模型编译成动态库加载到程序中这个动态库里的本构会替代内置模型参与每个zone的应力更新计算。这个路线的核心优势是物理一致性。每一个应变增量进来之后先做弹性试探再判断屈服、做塑性修正每一步的应力增量、应变增量都在眼前能量积分和应力更新同步完成弹性能、塑性耗散能、塑性功的拆分是干净清晰的。对需要做岩爆能量演化规律研究、或者自定义了非标准屈服准则的开发者来说这是绕不开的路径。它的缺点是工程量明显大要搭建编译环境、理解本构接口的数据结构、处理参数传递和调用约定Debug调试周期长。我见过不少同学花了两三周才把自编本构顺利跑起来第一周基本都在和环境较劲。2.3 两条路线的选型建议这里给一个非常具体的选型标准你可以直接对照自己的场景来判断。如果你只是做工程分析、方案对比需要能量云图、区域能量统计选FISH脚本路线把精力放在模型边界和工况设计上。如果你在做学术研究要讨论塑性耗散、损伤演化、能量释放率这类机制问题或者你的本构模型本身就自带特殊屈服面那就必须上自定义本构。还有一条补充建议学术论文里如果要把能量分析作为核心论据评审很可能会追问能量拆分路径是否严格这时候用FISH公式法得到的能量云图容易受到质疑用自定义本构的能量积分更有说服力。反之工程报告用能量云图做辅助说明FISH路线完全足够成本低、易复现。用一张表把两边摆清楚对比维度FISH脚本路线自定义本构路线开发语言FISH内置脚本C编译为DLL计算口径按弹性公式由当前应力反推随应力更新逐时步积分塑性耗能拆分不支持严格拆分支持开发周期1-3天1-4周适用场景工程方案对比、能量云图辅助分析岩爆机制研究、自定义屈服准则能量演化维护成本低随命令流分发较高需版本兼容维护我在实际项目中两种路线都用过总体的感觉是单看能量云图的视觉冲击力两者差别不大但涉及能量守恒校核和耗散能定量评价时只有自定义本构路线能给你严格的数学物理一致性。3. 实操第一步用FISH脚本把应变能密度云图画出来3.1 计算公式怎么选为什么我推荐体积变形能加畸变能FLAC里单元应力状态是六个分量三个正应力、三个剪应力应变能密度是单位体积储存的弹性应变能。等效应变能密度的严格定义是应力张量与弹性应变张量的双点积的一半。但如果直接用六个分量做张量缩并你需要同时存下弹性应变张量而且对弹塑性模型还要区分弹性应变和塑性应变比较麻烦。工程上更常用的做法是把弹性能密度拆成两部分体积变形能Uv和畸变能Ud两者之和就是总弹性应变能密度。体积变形能对应体积压缩或膨胀储存的能量畸变能对应形状改变储存的能量。这两个分量的物理意义各有用途体积变形能高意味着围岩处于强压缩状态从能量角度更接近启动型岩爆的储能条件畸变能高则意味着剪切畸变剧烈更接近剪切型破坏的能量来源。分开算还有个实际好处在云图显示时你可以分别看Uv和Ud判断一个高能区的能量到底以压缩性质为主还是以剪切性质为主。公式如下Uv (1 - 2ν) / (6E) × (σ₁ σ₂ σ₃)²Ud (1 ν) / (6E) × [(σ₁ - σ₂)² (σ₂ - σ₃)² (σ₃ - σ₁)²]总弹性能密度 Ue Uv Ud。其中σ₁、σ₂、σ₃是三个主应力E是弹性模量ν是泊松比。这套公式在线弹性范围严格成立单元进入塑性后Ue的含义会逐渐从“真实弹性应变能”退化为“按当前应力和弹性参数折算的等效弹性能”这个误差在弹塑性边界附近需要有所认识不影响高弹性区内相对比较。3.2 从零开始写FISH脚本遍历zone、调用应力、写入extra接下来是实际操作。我以FLAC3D 7.0的FISH语法来写老版本如FLAC3D 5.0/6.0的接口有一些区别但逻辑完全一致。第一步是写一个计算能量密度的函数在函数内部遍历所有zone读出应力分量的六个值代入公式计算再把结果写入zone的extra槽位。FLAC3D里每个zone自带extra变量默认需要预先指定或直接在FISH里用zone.extra(z, index)读写这里我用第1个extra槽存总能量密度第2个槽存体积变形能密度第3个槽存畸变能密度后面画云图和统计都方便。def energy_density local zm zone.list loop foreach local z : zm local sx zone.stress.xx(z) local sy zone.stress.yy(z) local sz zone.stress.zz(z) local sxy zone.stress.xy(z) local syz zone.stress.yz(z) local szx zone.stress.zx(z) local p (sx sy sz) / 3.0 local sig1 zone.stress.norm(z,1) local sig3 zone.stress.norm(z,3) local sig2 zone.stress.norm(z,2) local Uv (1.0 - 2.0 * v_mod) / (6.0 * e_mod) * (sig1 sig2 sig3)^2 local Ud (1.0 v_mod) / (6.0 * e_mod) * ((sig1 - sig2)^2 (sig2 - sig3)^2 (sig3 - sig1)^2) zone.extra(z,1) Uv Ud zone.extra(z,2) Uv zone.extra(z,3) Ud endloop end energy_density这里e_mod和v_mod是全局变量分别对应弹性模量和泊松比建议直接从你的材料参数里赋值而不是在脚本里写死这样换材料参数时不用改脚本。我在公式里用的是主应力表达式因为FLAC3D内置了zone.stress.norm函数可以直接取三个主应力比从剪应力分量里换算等效应力干净得多。函数写完后调用时机是关键。如果你在求解前调用一次此时应力还是初始地应力场云图是一片均匀的背景值如果你在求解完成后调用一次得到的是最终状态的能量分布。想追踪能量随开挖的演化就要在每步开挖求解后循环调用。我习惯把能量计算封装成一个独立函数在外层控制流里显式调用而不是直接挂在求解循环里。这样逻辑清晰排查问题也方便。做完了记得用zone.extra输出云图——在FLAC3D里直接把显示属性切换到extra 1就可以看到能量密度云图不用额外导出数据。3.3 全模型能量时程统计怎么做光有空间分布还不够很多时候需要看能量随时间步的演化过程比如开挖过程中全模型弹性能总量是增加还是减小峰值出现在哪个工况。做法同样很简单写一个累计函数在每次能量密度计算完成后把所有单元的Ue乘以单元体积再累加。global total_energy 0.0 def energy_total total_energy 0.0 local zm zone.list loop foreach local z : zm local Ue zone.extra(z,1) total_energy Ue * zone.volume(z) endloop end energy_total这个total_energy就是当前时刻全模型的弹性应变能总量。把它用history记录功能追踪就能得到能量时程曲线。这里有一个非常重要的注意事项FLAC3D的history默认按计算步记录如果你想让history记录的是真实物理时间步对应的值需要根据求解步数设置记录间隔。比如每个工况求解2000步你想每个工况记录一次能量值那history的间隔就设成2000。否则你得到的是密密麻麻的时步序列画图还得自己重采样很麻烦。累加总量时还有一个边界问题模型四周边界的约束对能量统计有没有影响如果用固定边界边界附近单元在初始地应力加载阶段就积累了相当的应变能这部分能量属于“初始储能”分析开挖卸荷效应时通常要把它扣除。更干净的做法是在开挖前记录初始总能量作为基准后面每个阶段统计的是相对变化量delta_total_energy。我在做采动模拟时都会额外输出一个“能量增量”曲线比绝对总量曲线更说明问题。3.4 FISH路线容易被忽略的三个影响可靠性的细节第一个细节是单元几何退化。模型里如果有四面体退化单元或者过度畸变的zone单元体积计算和应力积分都会带入误差能量密度计算本身公式没问题但乘上单位体积后误差会被放大。建模时尽量保证网格质量能量分析对网格的敏感程度比应力分析更高我踩过网格太乱导致能量云图出现异常高值区的坑。第二个细节是静态求解时能量不一定是单调变化的。FLAC的静态求解本质是动力松弛阻尼在吸收动能能量在单元间传递早期时步能量波动大是正常现象不要看到能量曲线抖一下就怀疑脚本写错了。等不平衡力收敛到足够小能量曲线趋于平稳取平稳段的末值作为该工况能量值。第三个细节是extra槽位数量的预设。有些老版本需要提前配置extra数量比如config zextra 5否则运行到zone.extra赋值时会报错新版本虽然支持动态扩展但养成提前配置的习惯没有坏处。4. 进阶自定义本构模型里做能量积分4.1 开发框架和需要了解的关键接口FISH路线能满足工程分析需求但如果你要真正把塑性耗散能从弹性能里剥离出来或者你的本构模型是自定义的非线性屈服准则那就得写自定义本构。FLAC3D的用户自定义本构模型基于VC开发编译后是一个DLL在求解时由主程序加载。本构模型的核心是继承程序提供的基础模型类重写几个关键方法初始化方法负责分配内存和设置默认参数属性读写方法负责和FISH/参数面板交换材料参数运行方法是重头戏每个时步对每个zone调用一次接收当前应力状态和应变增量更新应力状态并返回新的应力张量。此外还需要实现应变增量计算、状态指示、能量相关变量输出等接口。我第一次接触这个框架的时候最难受的是理解“应变增量驱动”这个概念。本构模型的run方法在每个时步拿到的是应变增量不是应变总量应力更新全靠累计。这意味着你的一切内变量包括塑性应变、硬化参数、能量内变量都必须自己维护、自己累加。理解了这个后面写能量积分就是顺理成章的事能量本来就该和应力应变增量绑定在增量过程中累加。4.2 弹性应变能与塑性耗散能的增量积分流程在自定义本构里做能量积分核心逻辑是配合应力更新过程同步记账。我以摩尔库伦类弹塑性模型为例把流程拆开讲。每一步应变增量dε进来后先做弹性试探用弹性刚度矩阵把dε映射成试探应力增量得到试探应力。此时我们不知道单元会不会屈服所以先按弹性路径计算这部分应变增量对应的总功密度增量公式是dW (σ_old σ_trial) / 2 · dε用当前时刻和试探时刻应力的平均值乘应变增量等于梯形积分精度比单纯用σ_old高我建议直接用它。接下来做屈服判断如果试探应力在屈服面内说明没有塑性流动这部分dW全部计入弹性应变能增量。如果试探应力越过了屈服面就需要做塑性修正把试探应力投影回屈服面得到一个应力修正量dσ_c。此时真实应力增量等于试探应力增量减掉修正量但能量分类不是简单照这个公式拆。严格的做法是先在弹性路径下把dW计入弹性应变能再做塑性修正计算修正导致的能量损失也就是塑性耗散能增量dWp dσ_c · dε / 2然后从弹性应变能里扣掉dWp。这样每一个增量步结束时弹性能增量、塑性耗散能增量、塑性功增量都是干净的。还有一种工程简化做法只在屈服单元里把超出屈服后那部分应变能直接归类为耗散能不计算修正量这个做法速度快但物理性差论文里用的话容易被深究我不推荐。4.3 调试自定义本构时我觉得最值得分享的几条经验写自定义本构最磨人的不是本构方程本身而是编译接口和调试两件事。我分享几条经验。第一环境匹配是最大坑。FLAC3D不同版本对C编译器的要求不一样用的开发环境和接口头文件必须和主程序版本严格对应。很多同学编译成功了但加载时提示接口版本不兼容就是这个原因。解决方式很笨但在理官网下载对应版本的开发包按开发包里的示例工程改代码不要自己新建空工程从零搭环境。第二加一个“调试开关”参数到本构模型里。这个开关控制是否输出中间变量比如屈服状态、塑性修正量、能量增量等输出到文件或者通过FISH变量读取。跑小模型时打开跑大模型时关掉。没有这个习惯一旦跑完发现能量曲线异常你只能盲猜调试成本极高。第三先从单zone单元测试开始。很多团队直接拿完整工程模型测试新本构出了问题根本分不清是模型边界问题还是本构问题。正确打法是把模型缩到一个单元加上已知的加载路径比如单轴压缩、等向压缩算完后对比解析解。我调试能量积分时就是先做单轴压缩试验手算出单元的弹性应变能和塑性耗散能解析值和DLL输出对上了才敢跑复杂模型。另外提醒一下自定义本构里的能量变量虽然可以作为模型属性存储但输出到云图还需要额外步骤。通常做法是通过FISH访问zone的应变能密度内变量或者在本构里写一个返回函数再在FLAC3D里绑定到zone.extra上。不同接口版本的实现方式略有差别建议直接用开发包示例里的“用户自定义输出量”模板。5. 常见问题与排查技巧实录5.1 高频问题速查表我在帮别人调试能量分析脚本和本构的过程中整理了一份高频问题清单先列成表再挑几个重点展开。现象可能原因排查思路能量云图出现负值单元局部发生卸载弹性应变能释放属于正常物理现象关注的是高正值区全模型总能量随时间步持续增长不收敛未扣除初始地应力能量或阻尼耗能未被区分以开挖前状态为基准统计增量能量值量级明显偏大或偏小单位换算错误MPa、m、MJ混用统一用国际单位或严格E模量单位换算塑性区能量密度异常高FISH公式法不适用于严重屈服区改用自定义本构或只对弹性区做能量判据加载DLL提示接口版本不兼容编译器版本和开发包不匹配用官方开发包示例工程重建自定义本构跑复杂模型崩溃内变量内存访问越界缩小模型、用调试开关定位崩溃时步5.2 能量不守恒是排查的重灾区我遇到最多、也最让人头疼的就是“能量账对不上”的问题。做能量分析时弹性应变能总量的变化理论上应该等于外力做功减去各种耗散但在FLAC这类显式求解程序里能量平衡天然有一个难点系统里有动能和阻尼耗散两条非应变能路径。静态求解中阻尼不断把动能转化为热量这部分能量从力学角度“消失”了但它不是弹性应变能。所以如果你统计的弹性应变能总量曲线出现先猛涨后缓慢下降的形态不要急着怀疑脚本很可能是阻尼耗能在求解初期吸收了部分冲击能量。排查思路我总结成三步第一步用一个纯弹性小球或单轴压缩校核模型打开或关闭阻尼分别跑一遍看能量曲线是否平滑和无阻尼时接近直线以此确认阻尼的影响范围。第二步检查边界条件。如果把固定边界改成自由场边界或黏滞边界边界上会通过波的透射带走能量这部分能量也不在单元应变能里需要在统计口径中注明。第三步检查是否记录了初始地应力加载阶段的能量。这是最常见的人是问题模型在自重和边界应力作用下已经达到初始平衡初始能量是一个很大的基础值开挖后总能量变化可能只有这个基础值的几百分之几如果你没减掉初始值能量曲线会“平”得什么都看不出来。5.3 单位换算和可视化的坑单位问题是能量分析里隐蔽性最强的坑。FLAC本身没有强制单位制你输入应力用Pa、弹模用Pa网格尺寸用m那能量密度单位就是J/m³总能量单位就是J。但岩土工程师更习惯用MPa一旦弹模写成e5 MPa其实是5e9 Pa而网格尺寸用m能量密度数值读起来就是以MJ/m³为单位的画云图颜色范围可能漂亮但总量算出来会差6个数量级。我见过真实的案例某同学全模型总能量统计出来是几百想着量级不对但应力云图看着完全正常最后发现就是弹模单位写错导致能量单位换算翻车。建议的做法是脚本里固定一套单位并在注释里写明比如“E_mod 5e9; ; Pa换算后能量密度单位J/m³”全部转成国际单位再参与计算输出云图前再按需要转成MPa量级。云图显示方面有两个实用技巧。第一能量密度分布往往动态范围很大高能区和低能区差两三个数量级很正常直接用默认色标高能区外的区域全是同一个颜色看不出空间分布。解决办法是把云图显示范围手动限定在感兴趣的能量区间比如只看能量密度前百分之十的高值区这样能量积聚带会非常清楚。第二用切片图看能量云图比表面云图更直观。三维模型表面能量往往被浅部低能量单元覆盖内部高能区看不出来切一个剖面图能量积聚核的位置一目了然。6. 一点个人经验从量级核对开始别急着上复杂模型最后聊几句实操心得。我做能量分析最大的体会是能量参数和应力参数不同它天生就带“积分”属性是累计量所以对模型的初始状态、边界条件、加载历史特别敏感。很多人一上来就把脚本写好、跑通模型然后盯着能量云图开始解读却忘了问一句“这个数值量级对不对”。我自己的习惯是每次都先构造一个可以手算出解析解的小模型比如单轴压缩的标准试件弹性模量、泊松比已知加载力已知先手算出理论弹性能再用脚本跑一遍看能不能对上。这一步花的时间不超过半小时却能挡住百分之八十的后续返工。能量分析如果量级没对上后面读出的所有“规律”都可能是假象。另外能量分析是个视角不是个孤立的功能。它最好和塑性区分布、应力路径放在一起看。高能量密度区域是不是恰好对应后期破坏区塑性耗散能激增的时刻是不是和位移突变时刻同步这些交叉验证能让能量分析的结果真正为工程决策提供帮助而不是只产出一张好看的红黄蓝云图。后面有机会我会再写一篇自定义本构能量积分代码的全注释版把每个关键段落的C实现都贴出来。你有具体的岩爆分析或能量统计需求也欢迎带模型来讨论这类问题聊起来比单看公式有意思得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑